diff options
7 files changed, 358 insertions, 2 deletions
diff --git a/src/components/application_manager/include/application_manager/commands/mobile/show_request.h b/src/components/application_manager/include/application_manager/commands/mobile/show_request.h index cbe2ca396a..a10997bacd 100644 --- a/src/components/application_manager/include/application_manager/commands/mobile/show_request.h +++ b/src/components/application_manager/include/application_manager/commands/mobile/show_request.h @@ -78,6 +78,17 @@ class ShowRequest : public CommandRequestImpl { */ bool CheckStringsOfShowRequest(); + /** + * @brief Handle the conversion of metadata information from the incoming + * mobile json message format to the outgoing hmi json message format + */ + void HandleMetadata(const char* field_id, + int32_t field_index, + smart_objects::SmartObject& msg_params); + + mobile_apis::Result::eType core_result_code_; + std::string core_response_info_; + DISALLOW_COPY_AND_ASSIGN(ShowRequest); }; diff --git a/src/components/application_manager/include/application_manager/smart_object_keys.h b/src/components/application_manager/include/application_manager/smart_object_keys.h index ccac1ec67b..25fa435364 100644 --- a/src/components/application_manager/include/application_manager/smart_object_keys.h +++ b/src/components/application_manager/include/application_manager/smart_object_keys.h @@ -93,6 +93,7 @@ extern const char* main_field_1; extern const char* main_field_2; extern const char* main_field_3; extern const char* main_field_4; +extern const char* metadata_tags; extern const char* eta; extern const char* time_to_destination; extern const char* total_distance; @@ -410,6 +411,7 @@ namespace hmi_request { extern const char* parent_id; extern const char* field_name; extern const char* field_text; +extern const char* field_types; extern const char* alert_strings; extern const char* duration; extern const char* soft_buttons; diff --git a/src/components/application_manager/src/commands/mobile/show_request.cc b/src/components/application_manager/src/commands/mobile/show_request.cc index cf2509cdb9..5b8e98d7ea 100644 --- a/src/components/application_manager/src/commands/mobile/show_request.cc +++ b/src/components/application_manager/src/commands/mobile/show_request.cc @@ -45,10 +45,46 @@ namespace commands { ShowRequest::ShowRequest(const MessageSharedPtr& message, ApplicationManager& application_manager) - : CommandRequestImpl(message, application_manager) {} + : CommandRequestImpl(message, application_manager) + , core_result_code_(mobile_apis::Result::INVALID_ENUM) {} ShowRequest::~ShowRequest() {} +void ShowRequest::HandleMetadata(const char* field_id, + int32_t field_index, + smart_objects::SmartObject& msg_params) { + smart_objects::SmartObject& metadata_tags = + (*message_)[strings::msg_params][strings::metadata_tags]; + + if (metadata_tags.keyExists(field_id)) { + if (field_index != -1) { + msg_params[hmi_request::show_strings][field_index] + [hmi_request::field_types] = + smart_objects::SmartObject(smart_objects::SmartType_Array); + + const size_t num_tags = metadata_tags[field_id].length(); + for (size_t i = 0; i < num_tags; ++i) { + const int32_t current_tag = metadata_tags[field_id][i].asInt(); + msg_params[hmi_request::show_strings][field_index] + [hmi_request::field_types][i] = current_tag; + } + } else { + LOG4CXX_INFO(logger_, + "metadata tag provided with no item for " + << field_id << ", ignoring with warning"); + // tag provided with no item, ignore with warning + if (mobile_apis::Result::INVALID_ENUM == core_result_code_) { + core_result_code_ = mobile_apis::Result::WARNINGS; + core_response_info_ = + "Metadata tag was provided for a field with no data."; + } + } + } else { + LOG4CXX_INFO(logger_, + "No metadata tagging provided for field: " << field_id); + } +} + void ShowRequest::Run() { LOG4CXX_AUTO_TRACE(logger_); @@ -125,38 +161,53 @@ void ShowRequest::Run() { smart_objects::SmartObject(smart_objects::SmartType_Array); int32_t index = 0; + int32_t main_field_1_index = -1; if ((*message_)[strings::msg_params].keyExists(strings::main_field_1)) { msg_params[hmi_request::show_strings][index][hmi_request::field_name] = static_cast<int32_t>(hmi_apis::Common_TextFieldName::mainField1); msg_params[hmi_request::show_strings][index][hmi_request::field_text] = (*message_)[strings::msg_params][strings::main_field_1]; + main_field_1_index = index; ++index; } + int32_t main_field_2_index = -1; if ((*message_)[strings::msg_params].keyExists(strings::main_field_2)) { msg_params[hmi_request::show_strings][index][hmi_request::field_name] = static_cast<int32_t>(hmi_apis::Common_TextFieldName::mainField2); msg_params[hmi_request::show_strings][index][hmi_request::field_text] = (*message_)[strings::msg_params][strings::main_field_2]; + main_field_2_index = index; ++index; } + int32_t main_field_3_index = -1; if ((*message_)[strings::msg_params].keyExists(strings::main_field_3)) { msg_params[hmi_request::show_strings][index][hmi_request::field_name] = static_cast<int32_t>(hmi_apis::Common_TextFieldName::mainField3); msg_params[hmi_request::show_strings][index][hmi_request::field_text] = (*message_)[strings::msg_params][strings::main_field_3]; + main_field_3_index = index; ++index; } + int32_t main_field_4_index = -1; if ((*message_)[strings::msg_params].keyExists(strings::main_field_4)) { msg_params[hmi_request::show_strings][index][hmi_request::field_name] = static_cast<int32_t>(hmi_apis::Common_TextFieldName::mainField4); msg_params[hmi_request::show_strings][index][hmi_request::field_text] = (*message_)[strings::msg_params][strings::main_field_4]; + main_field_4_index = index; ++index; } + if ((*message_)[strings::msg_params].keyExists(strings::metadata_tags)) { + HandleMetadata(strings::main_field_1, main_field_1_index, msg_params); + HandleMetadata(strings::main_field_2, main_field_2_index, msg_params); + HandleMetadata(strings::main_field_3, main_field_3_index, msg_params); + HandleMetadata(strings::main_field_4, main_field_4_index, msg_params); + } + if ((*message_)[strings::msg_params].keyExists(strings::media_clock)) { msg_params[hmi_request::show_strings][index][hmi_request::field_name] = static_cast<int32_t>(hmi_apis::Common_TextFieldName::mediaClock); @@ -239,8 +290,15 @@ void ShowRequest::on_event(const event_engine::Event& event) { response_info = message[strings::params][hmi_response::message].asString(); } + mobile_apis::Result::eType converted_result_code = + MessageHelper::HMIToMobileResult(result_code); + if (mobile_apis::Result::SUCCESS == converted_result_code && + mobile_apis::Result::INVALID_ENUM != core_result_code_) { + converted_result_code = core_result_code_; + response_info = core_response_info_; + } SendResponse(result, - MessageHelper::HMIToMobileResult(result_code), + converted_result_code, response_info.empty() ? NULL : response_info.c_str(), &(message[strings::msg_params])); break; diff --git a/src/components/application_manager/src/smart_object_keys.cc b/src/components/application_manager/src/smart_object_keys.cc index d5041ef836..45bab026b4 100644 --- a/src/components/application_manager/src/smart_object_keys.cc +++ b/src/components/application_manager/src/smart_object_keys.cc @@ -57,6 +57,7 @@ const char* main_field_1 = "mainField1"; const char* main_field_2 = "mainField2"; const char* main_field_3 = "mainField3"; const char* main_field_4 = "mainField4"; +const char* metadata_tags = "metadataTags"; const char* eta = "eta"; const char* time_to_destination = "timeToDestination"; const char* total_distance = "totalDistance"; @@ -368,6 +369,7 @@ namespace hmi_request { const char* parent_id = "parentID"; const char* field_name = "fieldName"; const char* field_text = "fieldText"; +const char* field_types = "fieldTypes"; const char* alert_strings = "alertStrings"; const char* duration = "duration"; const char* soft_buttons = "softButtons"; diff --git a/src/components/application_manager/test/commands/mobile/show_test.cc b/src/components/application_manager/test/commands/mobile/show_test.cc index 86889ac5cd..29ab902f5c 100644 --- a/src/components/application_manager/test/commands/mobile/show_test.cc +++ b/src/components/application_manager/test/commands/mobile/show_test.cc @@ -150,6 +150,59 @@ class ShowRequestTest : public CommandRequestTest<CommandsTestMocks::kIsNice> { EXPECT_CALL(*mock_app_, set_show_command(_)).Times(0); } + void TestSetupHelperWithMetadata( + MessageSharedPtr msg, + hmi_apis::Common_TextFieldName::eType field_name, + const char* field, + size_t num_tags, + int32_t* field_tags, + bool set_field_text = true) { + SmartObject msg_params(smart_objects::SmartType_Map); + (*msg)[am::strings::params][am::strings::connection_key] = kConnectionKey; + (*msg)[am::strings::params][am::strings::function_id] = kFunctionID; + if (set_field_text) { + msg_params[field] = text_field_; + } + msg_params[am::strings::metadata_tags][field] = + smart_objects::SmartObject(smart_objects::SmartType_Array); + for (size_t i = 0; i < num_tags; ++i) { + const int32_t current_tag = field_tags[i]; + msg_params[am::strings::metadata_tags][field][i] = current_tag; + } + (*msg)[am::strings::msg_params] = msg_params; + + EXPECT_EQ((*msg)[am::strings::msg_params], msg_params); + + EXPECT_CALL(app_mngr_, application(kConnectionKey)) + .WillOnce(Return(mock_app_)); + EXPECT_CALL(*mock_app_, app_id()).WillOnce(Return(kAppId)); + + msg_params.erase(field); + msg_params.erase(am::strings::metadata_tags); + + msg_params[am::strings::app_id] = kAppId; + msg_params[am::hmi_request::show_strings] = + smart_objects::SmartObject(smart_objects::SmartType_Array); + if (set_field_text) { + msg_params[am::hmi_request::show_strings][0] + [am::hmi_request::field_name] = + static_cast<int32_t>(field_name); + msg_params[am::hmi_request::show_strings][0] + [am::hmi_request::field_text] = text_field_; + msg_params[am::hmi_request::show_strings][0] + [am::hmi_request::field_types] = + smart_objects::SmartObject(smart_objects::SmartType_Array); + for (size_t i = 0; i < num_tags; ++i) { + const int32_t current_tag = field_tags[i]; + msg_params[am::hmi_request::show_strings][0] + [am::hmi_request::field_types][i] = current_tag; + } + } + + EXPECT_CALL(app_mngr_, ManageHMICommand(_)); + EXPECT_CALL(*mock_app_, set_show_command(msg_params)); + } + void SetUp() OVERRIDE { Mock::VerifyAndClearExpectations(&mock_message_helper_); } @@ -582,6 +635,132 @@ TEST_F(ShowRequestTest, Run_MainField4_WrongSyntax) { command->Run(); } +TEST_F(ShowRequestTest, Run_MainField1_MetadataTag) { + MessageSharedPtr msg = CreateMsgParams(); + + SharedPtr<ShowRequest> command(CreateCommand<ShowRequest>(msg)); + + text_field_ = "Main_Field_1"; + const size_t num_tags = 1; + int32_t tags[num_tags] = {hmi_apis::Common_MetadataType::mediaArtist}; + TestSetupHelperWithMetadata(msg, + hmi_apis::Common_TextFieldName::mainField1, + am::strings::main_field_1, + num_tags, + tags); + command->Run(); +} + +TEST_F(ShowRequestTest, Run_MainField1_MultipleMetadataTags) { + MessageSharedPtr msg = CreateMsgParams(); + + SharedPtr<ShowRequest> command(CreateCommand<ShowRequest>(msg)); + + text_field_ = "Main_Field_1"; + const size_t num_tags = 5; + int32_t tags[num_tags] = {hmi_apis::Common_MetadataType::mediaTitle, + hmi_apis::Common_MetadataType::mediaArtist, + hmi_apis::Common_MetadataType::rating, + hmi_apis::Common_MetadataType::humidity, + hmi_apis::Common_MetadataType::currentTemperature}; + TestSetupHelperWithMetadata(msg, + hmi_apis::Common_TextFieldName::mainField1, + am::strings::main_field_1, + num_tags, + tags); + command->Run(); +} + +TEST_F(ShowRequestTest, Run_MainField2_MetadataTag) { + MessageSharedPtr msg = CreateMsgParams(); + + SharedPtr<ShowRequest> command(CreateCommand<ShowRequest>(msg)); + + text_field_ = "Main_Field_2"; + const size_t num_tags = 1; + int32_t tags[num_tags] = {hmi_apis::Common_MetadataType::mediaArtist}; + TestSetupHelperWithMetadata(msg, + hmi_apis::Common_TextFieldName::mainField2, + am::strings::main_field_2, + num_tags, + tags); + command->Run(); +} + +TEST_F(ShowRequestTest, Run_MainField3_MetadataTag) { + MessageSharedPtr msg = CreateMsgParams(); + + SharedPtr<ShowRequest> command(CreateCommand<ShowRequest>(msg)); + + text_field_ = "Main_Field_3"; + const size_t num_tags = 1; + int32_t tags[num_tags] = {hmi_apis::Common_MetadataType::mediaArtist}; + TestSetupHelperWithMetadata(msg, + hmi_apis::Common_TextFieldName::mainField3, + am::strings::main_field_3, + num_tags, + tags); + command->Run(); +} + +TEST_F(ShowRequestTest, Run_MainField4_MetadataTag) { + MessageSharedPtr msg = CreateMsgParams(); + + SharedPtr<ShowRequest> command(CreateCommand<ShowRequest>(msg)); + + text_field_ = "Main_Field_4"; + const size_t num_tags = 1; + int32_t tags[num_tags] = {hmi_apis::Common_MetadataType::mediaArtist}; + TestSetupHelperWithMetadata(msg, + hmi_apis::Common_TextFieldName::mainField4, + am::strings::main_field_4, + num_tags, + tags); + command->Run(); +} + +TEST_F(ShowRequestTest, Run_MainField1_MetadataTagWithNoFieldData) { + MessageSharedPtr msg = CreateMsgParams(); + + SharedPtr<ShowRequest> command(CreateCommand<ShowRequest>(msg)); + + text_field_ = "Main_Field_1"; + const size_t num_tags = 1; + int32_t tags[num_tags] = {hmi_apis::Common_MetadataType::mediaArtist}; + TestSetupHelperWithMetadata(msg, + hmi_apis::Common_TextFieldName::mainField1, + am::strings::main_field_1, + num_tags, + tags, + false); + command->Run(); + + MessageSharedPtr ev_msg = CreateMessage(smart_objects::SmartType_Map); + (*ev_msg)[am::strings::params][am::hmi_response::code] = + hmi_apis::Common_Result::SUCCESS; + (*ev_msg)[am::strings::msg_params][am::strings::app_id] = kConnectionKey; + (*ev_msg)[am::strings::msg_params][am::strings::info] = ""; + + Event event(hmi_apis::FunctionID::UI_Show); + event.set_smart_object(*ev_msg); + + MessageSharedPtr ui_command_result; + EXPECT_CALL( + app_mngr_, + ManageMobileCommand(_, am::commands::Command::CommandOrigin::ORIGIN_SDL)) + .WillOnce(DoAll(SaveArg<0>(&ui_command_result), Return(true))); + + command->on_event(event); + + EXPECT_EQ((*ui_command_result)[am::strings::msg_params][am::strings::success] + .asBool(), + true); + EXPECT_EQ( + (*ui_command_result)[am::strings::msg_params][am::strings::result_code] + .asInt(), + static_cast<int32_t>(mobile_apis::Result::WARNINGS)); +} + TEST_F(ShowRequestTest, Run_MediaClock_SUCCESS) { MessageSharedPtr msg = CreateMsgParams(); diff --git a/src/components/interfaces/HMI_API.xml b/src/components/interfaces/HMI_API.xml index 554461cc86..32360aa357 100644 --- a/src/components/interfaces/HMI_API.xml +++ b/src/components/interfaces/HMI_API.xml @@ -559,6 +559,45 @@ <element name="turnText"/> </enum> +<enum name="MetadataType"> + <element name="mediaTitle"> + <description>The data in this field contains the title of the currently playing audio track.</description> + </element> + <element name="mediaArtist"> + <description>The data in this field contains the artist or creator of the currently playing audio track.</description> + </element> + <element name="mediaAlbum"> + <description>The data in this field contains the album title of the currently playing audio track.</description> + </element> + <element name="mediaYear"> + <description>The data in this field contains the creation year of the currently playing audio track.</description> + </element> + <element name="mediaGenre"> + <description>The data in this field contains the genre of the currently playing audio track.</description> + </element> + <element name="mediaStation"> + <description>The data in this field contains the name of the current source for the media.</description> + </element> + <element name="rating"> + <description>The data in this field is a rating.</description> + </element> + <element name="currentTemperature"> + <description>The data in this field is the current temperature.</description> + </element> + <element name="maximumTemperature"> + <description>The data in this field is the maximum temperature for the day.</description> + </element> + <element name="minimumTemperature"> + <description>The data in this field is the minimum temperature for the day.</description> + </element> + <element name="weatherTerm"> + <description>The data in this field describes the current weather (ex. cloudy, clear, etc.).</description> + </element> + <element name="humidity"> + <description>The data in this field describes the current humidity value.</description> + </element> +</enum> + <enum name="ImageFieldName"> <element name="softButtonImage"> <description>The image field for SoftButton</description> @@ -2092,6 +2131,9 @@ <param name="fieldText" type="String" maxlength="500" mandatory="true"> <description>The text itself.</description> </param> + <param name="fieldTypes" type="Common.MetadataType" minsize="0" maxsize="5" array="true" mandatory="false"> + <description>The type of data contained in the field.</description> + </param> </struct> <struct name="KeyboardProperties"> diff --git a/src/components/interfaces/MOBILE_API.xml b/src/components/interfaces/MOBILE_API.xml index 2d550f04f2..73fe9f3d0c 100644 --- a/src/components/interfaces/MOBILE_API.xml +++ b/src/components/interfaces/MOBILE_API.xml @@ -756,6 +756,45 @@ </enum>
+ <enum name="MetadataType">
+ <element name="mediaTitle">
+ <description>The data in this field contains the title of the currently playing audio track.</description>
+ </element>
+ <element name="mediaArtist">
+ <description>The data in this field contains the artist or creator of the currently playing audio track.</description>
+ </element>
+ <element name="mediaAlbum">
+ <description>The data in this field contains the album title of the currently playing audio track.</description>
+ </element>
+ <element name="mediaYear">
+ <description>The data in this field contains the creation year of the currently playing audio track.</description>
+ </element>
+ <element name="mediaGenre">
+ <description>The data in this field contains the genre of the currently playing audio track.</description>
+ </element>
+ <element name="mediaStation">
+ <description>The data in this field contains the name of the current source for the media.</description>
+ </element>
+ <element name="rating">
+ <description>The data in this field is a rating.</description>
+ </element>
+ <element name="currentTemperature">
+ <description>The data in this field is the current temperature.</description>
+ </element>
+ <element name="maximumTemperature">
+ <description>The data in this field is the maximum temperature for the day.</description>
+ </element>
+ <element name="minimumTemperature">
+ <description>The data in this field is the minimum temperature for the day.</description>
+ </element>
+ <element name="weatherTerm">
+ <description>The data in this field describes the current weather (ex. cloudy, clear, etc.).</description>
+ </element>
+ <element name="humidity">
+ <description>The data in this field describes the current humidity value.</description>
+ </element>
+ </enum>
+
<enum name="ImageFieldName">
<element name="softButtonImage">
<description>The image field for SoftButton</description>
@@ -976,6 +1015,21 @@ </param>
</struct>
+ <struct name="MetadataTags">
+ <param name="mainField1" type="MetadataType" minsize="0" maxsize="5" array="true" mandatory="false">
+ <description>The type of data contained in the "mainField1" text field.</description>
+ </param>
+ <param name="mainField2" type="MetadataType" minsize="0" maxsize="5" array="true" mandatory="false">
+ <description>The type of data contained in the "mainField2" text field.</description>
+ </param>
+ <param name="mainField3" type="MetadataType" minsize="0" maxsize="5" array="true" mandatory="false">
+ <description>The type of data contained in the "mainField3" text field.</description>
+ </param>
+ <param name="mainField4" type="MetadataType" minsize="0" maxsize="5" array="true" mandatory="false">
+ <description>The type of data contained in the "mainField4" text field.</description>
+ </param>
+ </struct>
+
<struct name="Choice">
<description>A choice is an option given to the user, which can be selected either by menu, or through voice recognition system.</description>
<param name="choiceID" type="Integer" minvalue="0" maxvalue="65535" mandatory="true"/>
@@ -3788,6 +3842,14 @@ </description>
</param>
+ <param name="metadataTags" type="MetadataTags" mandatory="false">
+ <description>
+ App defined metadata information. See MetadataTags. Uses mainField1, mainField2, mainField3, mainField4.
+ If omitted on supported displays, the currently set metadata tags will not change.
+ If any text field contains no tags, the metadata tag for that textfield should be removed.
+ </description>
+ </param>
+
</function>
<function name="Show" functionID="ShowID" messagetype="response">
|