summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authoragaliuzov <agaliuzov@luxoft.com>2016-04-06 17:33:34 +0300
committeragaliuzov <agaliuzov@luxoft.com>2016-04-06 17:33:34 +0300
commitc73c5976a96046d7ce2a5053362a5eef6e8a2b95 (patch)
tree6d44d23a5095b8efc7bfa6d86fd946decae36490 /src
parent5d116a9286bd5b4d43b95de185fb81aa6a7e7f93 (diff)
parent6808a52562978f1e01899573d77b47ad33dccff3 (diff)
downloadsdl_core-c73c5976a96046d7ce2a5053362a5eef6e8a2b95.tar.gz
Merge remote-tracking branch 'upstream/master' into develop
Diffstat (limited to 'src')
-rw-r--r--src/components/application_manager/CMakeLists.txt1
-rw-r--r--src/components/application_manager/include/application_manager/commands/mobile/dial_number_request.h19
-rw-r--r--src/components/application_manager/src/commands/mobile/dial_number_request.cc3
-rw-r--r--src/components/application_manager/src/commands/mobile/dial_number_response.cc3
-rw-r--r--src/components/application_manager/src/commands/mobile/system_request.cc426
-rw-r--r--src/components/application_manager/src/hmi_command_factory.cc13
-rw-r--r--src/components/application_manager/src/mobile_command_factory.cc9
-rw-r--r--src/components/interfaces/HMI_API.xml12
8 files changed, 420 insertions, 66 deletions
diff --git a/src/components/application_manager/CMakeLists.txt b/src/components/application_manager/CMakeLists.txt
index 963899e809..775ed7f349 100644
--- a/src/components/application_manager/CMakeLists.txt
+++ b/src/components/application_manager/CMakeLists.txt
@@ -297,6 +297,7 @@ file (GLOB MOBILE_COMMANDS_SOURCES
${AM_SOURCE_DIR}/src/commands/hmi/dial_number_request.cc
${AM_SOURCE_DIR}/src/commands/hmi/dial_number_response.cc
${AM_SOURCE_DIR}/src/commands/hmi/on_event_changed_notification.cc
+ ${AM_SOURCE_DIR}/src/commands/hmi/on_phone_call_notification.cc
)
set (HMI_COMMANDS_SOURCES_JSON
diff --git a/src/components/application_manager/include/application_manager/commands/mobile/dial_number_request.h b/src/components/application_manager/include/application_manager/commands/mobile/dial_number_request.h
index 0c046362e7..c2ed6ee4ff 100644
--- a/src/components/application_manager/include/application_manager/commands/mobile/dial_number_request.h
+++ b/src/components/application_manager/include/application_manager/commands/mobile/dial_number_request.h
@@ -1,6 +1,5 @@
/*
-
- Copyright (c) 2013, Ford Motor Company
+ Copyright (c) 2016, Ford Motor Company
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -54,7 +53,12 @@ class DialNumberRequest : public CommandRequestImpl {
/**
* \brief DialNumberRequest class destructor
**/
- virtual ~DialNumberRequest();
+ ~DialNumberRequest() OVERRIDE;
+
+ /**
+ * @brief Initialize request params
+ **/
+ bool Init() OVERRIDE;
/**
* @brief Initialize request params
@@ -64,7 +68,14 @@ class DialNumberRequest : public CommandRequestImpl {
/**
* @brief Execute command
**/
- virtual void Run();
+ void Run() OVERRIDE;
+
+ /**
+ * @brief Interface method that is called whenever new event received
+ *
+ * @param event The received event
+ */
+ void on_event(const event_engine::Event& event);
/**
* @brief Interface method that is called whenever new event received
diff --git a/src/components/application_manager/src/commands/mobile/dial_number_request.cc b/src/components/application_manager/src/commands/mobile/dial_number_request.cc
index 5c1cf18cf8..6e8f5e15ad 100644
--- a/src/components/application_manager/src/commands/mobile/dial_number_request.cc
+++ b/src/components/application_manager/src/commands/mobile/dial_number_request.cc
@@ -1,5 +1,4 @@
/*
-
Copyright (c) 2016, Ford Motor Company
All rights reserved.
@@ -131,7 +130,7 @@ void DialNumberRequest::on_event(const event_engine::Event& event) {
void DialNumberRequest::StripNumberParam(std::string& number) {
std::size_t found = 0;
while (std::string::npos !=
- (found = number.find_first_not_of("+0123456789"))) {
+ (found = number.find_first_not_of("+*#,;0123456789"))) {
number.erase(number.begin() + found);
}
(*message_)[strings::msg_params][strings::number] = number;
diff --git a/src/components/application_manager/src/commands/mobile/dial_number_response.cc b/src/components/application_manager/src/commands/mobile/dial_number_response.cc
index 3eba98fb96..1daab5a4e1 100644
--- a/src/components/application_manager/src/commands/mobile/dial_number_response.cc
+++ b/src/components/application_manager/src/commands/mobile/dial_number_response.cc
@@ -1,6 +1,5 @@
/*
-
- Copyright (c) 2013, Ford Motor Company
+ Copyright (c) 2016, Ford Motor Company
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/src/components/application_manager/src/commands/mobile/system_request.cc b/src/components/application_manager/src/commands/mobile/system_request.cc
index 3720b98c02..bede5b3f3b 100644
--- a/src/components/application_manager/src/commands/mobile/system_request.cc
+++ b/src/components/application_manager/src/commands/mobile/system_request.cc
@@ -33,7 +33,8 @@ Copyright (c) 2013, Ford Motor Company
#include <vector>
#include <string>
-#include <stdio.h>
+#include <map>
+#include <set>
#include "application_manager/commands/mobile/system_request.h"
#include "application_manager/application_manager_impl.h"
#include "application_manager/application_impl.h"
@@ -47,6 +48,368 @@ Copyright (c) 2013, Ford Motor Company
namespace application_manager {
+namespace {
+
+CREATE_LOGGERPTR_LOCAL(logger_, "ApplicationManager")
+
+const char* kQueryAppsValidationFailedPrefix =
+ ":QUERY_APPS_VALIDATION_FAILED: ";
+
+const unsigned int kVrSynonymLengthMax = 40U;
+const unsigned int kVrSynonymLengthMin = 1U;
+const unsigned int kTtsNameLengthMax = 500U;
+const unsigned int kVrArraySizeMax = 100U;
+const unsigned int kVrArraySizeMin = 1U;
+const unsigned int kUrlSchemaLengthMax = 255U;
+const unsigned int kPackageNameLengthMax = 255U;
+const unsigned int kAppIdLengthMax = 40U;
+const unsigned int kAppNameLengthMax = 100U;
+const unsigned int kLanguageArraySizeMax = 100U;
+
+class QueryAppsDataValidator {
+ public:
+ typedef std::set<std::string> SynonymsSet;
+ typedef std::map<std::string, SynonymsSet> SynonymsMap;
+
+ QueryAppsDataValidator(const smart_objects::SmartObject& object,
+ const ApplicationManagerImpl& manager)
+ : data_(object), manager_(manager) {}
+
+ bool Validate() const {
+ LOG4CXX_AUTO_TRACE(logger_);
+ if (!data_.isValid()) {
+ LOG4CXX_ERROR(logger_,
+ kQueryAppsValidationFailedPrefix
+ << "QueryApps response is not valid.");
+ return false;
+ }
+ if (!HasResponseKey()) {
+ return false;
+ }
+ return ValidateAppDataAndOsAndLanguagesData();
+ }
+
+ private:
+ bool HasResponseKey() const {
+ if (!data_.keyExists(json::response)) {
+ LOG4CXX_WARN(logger_,
+ kQueryAppsValidationFailedPrefix
+ << "QueryApps response does not contain '"
+ << json::response << "' parameter.");
+ return false;
+ }
+ return true;
+ }
+
+ bool ValidateAppDataAndOsAndLanguagesData() const {
+ const smart_objects::SmartArray* objects_array =
+ data_[json::response].asArray();
+ if (!objects_array) {
+ LOG4CXX_WARN(logger_,
+ kQueryAppsValidationFailedPrefix
+ << "QueryApps response is not array.");
+ return false;
+ }
+ const std::size_t arr_size(objects_array->size());
+ SynonymsMap synonyms_map;
+ for (std::size_t idx = 0; idx < arr_size; ++idx) {
+ const smart_objects::SmartObject& app_data = (*objects_array)[idx];
+
+ if (!app_data.isValid()) {
+ LOG4CXX_WARN(logger_,
+ kQueryAppsValidationFailedPrefix
+ << "Wrong application data in json file.");
+ return false;
+ }
+ std::set<std::string> app_ids_set;
+ if (!ValidateAppIdAndAppName(app_data, app_ids_set)) {
+ return false;
+ }
+ // Verify os and dependent languages data
+ std::string os_type;
+ if (app_data.keyExists(json::ios)) {
+ os_type = json::ios;
+ if (!app_data[os_type].keyExists(json::urlScheme)) {
+ LOG4CXX_WARN(logger_,
+ kQueryAppsValidationFailedPrefix
+ << "Can't find URL scheme in json file.");
+ return false;
+ }
+ if (app_data[os_type][json::urlScheme].asString().length() >
+ kUrlSchemaLengthMax) {
+ LOG4CXX_WARN(
+ logger_,
+ kQueryAppsValidationFailedPrefix
+ << "An urlscheme length exceeds maximum allowed ["
+ << app_data[os_type][json::urlScheme].asString().length()
+ << "]>[" << kUrlSchemaLengthMax << "]");
+ return false;
+ }
+ }
+ if (os_type.empty()) {
+ if (app_data.keyExists(json::android)) {
+ os_type = json::android;
+ if (!app_data[os_type].keyExists(json::packageName)) {
+ LOG4CXX_WARN(logger_,
+ kQueryAppsValidationFailedPrefix
+ << "Can't find package name in json file.");
+ return false;
+ }
+ if (app_data[json::android][json::packageName].asString().length() >
+ kPackageNameLengthMax) {
+ LOG4CXX_WARN(logger_,
+ kQueryAppsValidationFailedPrefix
+ << "Package name length ["
+ << app_data[json::android][json::packageName]
+ .asString()
+ .length() << "] exceeds max length ["
+ << kPackageNameLengthMax << "]in json file.");
+ return false;
+ }
+ }
+ }
+
+ if (os_type.empty()) {
+ LOG4CXX_WARN(logger_,
+ kQueryAppsValidationFailedPrefix
+ << "Can't find mobile OS type in json file.");
+ return false;
+ }
+
+ // Languages verification
+ if (!app_data[os_type].keyExists(json::languages)) {
+ LOG4CXX_WARN(logger_,
+ kQueryAppsValidationFailedPrefix
+ << "'languages' doesn't exist");
+ return false;
+ }
+ if (!ValidateLanguages(app_data[os_type][json::languages],
+ synonyms_map)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ bool ValidateAppIdAndAppName(const smart_objects::SmartObject& app_data,
+ std::set<std::string>& app_ids_set) const {
+ // Verify appid
+ if (!app_data.keyExists(json::appId)) {
+ LOG4CXX_WARN(logger_,
+ kQueryAppsValidationFailedPrefix
+ << "Can't find app ID in json file.");
+ return false;
+ }
+ // Verify appid length
+ const std::string app_id(app_data[json::appId].asString());
+ if (app_id.length() > kAppIdLengthMax) {
+ LOG4CXX_WARN(logger_,
+ kQueryAppsValidationFailedPrefix
+ << "An Object ID length exceeds maximum allowed ["
+ << app_id.length() << "]>[" << kAppIdLengthMax << "]");
+ return false;
+ }
+
+ // Verify that appid is unique
+ if (app_ids_set.find(app_id) != app_ids_set.end()) {
+ LOG4CXX_WARN(logger_,
+ kQueryAppsValidationFailedPrefix
+ << "An Object ID is not unigue [" << app_id << "]");
+ return false;
+ }
+ app_ids_set.insert(app_id);
+
+ // Verify that app is not registered yet
+ ApplicationSharedPtr registered_app =
+ manager_.application_by_policy_id(app_id);
+ if (registered_app) {
+ LOG4CXX_WARN(logger_,
+ kQueryAppsValidationFailedPrefix
+ << "Application with the same id: " << app_id
+ << " is registered already.");
+ return false;
+ }
+ // Verify app name exist
+ if (!app_data.keyExists(json::name)) {
+ LOG4CXX_WARN(logger_,
+ kQueryAppsValidationFailedPrefix
+ << "Can't find app name in json file.");
+ return false;
+ }
+ // And app name length
+ const std::string appName(app_data[json::name].asString());
+ if (appName.length() > kAppNameLengthMax) {
+ LOG4CXX_WARN(logger_,
+ kQueryAppsValidationFailedPrefix
+ << "Name of application exceeds maximum allowed ["
+ << appName.length() << "]>[" << kAppNameLengthMax
+ << "].");
+ return false;
+ }
+ return true;
+ }
+
+ bool ValidateLanguages(const smart_objects::SmartObject& languages,
+ SynonymsMap& synonyms_map) const {
+ bool default_language_found = false;
+ const size_t languages_array_size = languages.length();
+ if (languages_array_size > kLanguageArraySizeMax) {
+ LOG4CXX_WARN(logger_,
+ kQueryAppsValidationFailedPrefix
+ << "'languages' array exceeds max size ["
+ << languages_array_size << "]>[" << kLanguageArraySizeMax
+ << "]");
+ return false;
+ }
+ // Every language has ttsname string and vrsynonyms array
+ for (size_t idx = 0; idx < languages_array_size; ++idx) {
+ const smart_objects::SmartObject& language = languages.getElement(idx);
+ if (smart_objects::SmartType_Map != language.getType()) {
+ LOG4CXX_WARN(logger_,
+ kQueryAppsValidationFailedPrefix
+ << "language is not a map.");
+ return false;
+ }
+ if (language.length() != 1) {
+ LOG4CXX_WARN(logger_,
+ kQueryAppsValidationFailedPrefix
+ << "language map size is not equal 1.");
+ return false;
+ }
+ const std::string language_name = (*language.map_begin()).first;
+ if (!language_name.length()) {
+ LOG4CXX_WARN(logger_,
+ kQueryAppsValidationFailedPrefix
+ << "language name is empty");
+ return false;
+ }
+ // Verify default language defined
+ if (!(language_name).compare(json::default_)) {
+ default_language_found = true;
+ }
+ // Add set for synonyms' duplicates validation
+ if (synonyms_map.find(language_name) == synonyms_map.end()) {
+ synonyms_map[language_name] = SynonymsSet();
+ }
+ // ttsName verification
+ if (!language[language_name].keyExists(json::ttsName)) {
+ LOG4CXX_WARN(logger_,
+ kQueryAppsValidationFailedPrefix
+ << "'languages.ttsName' doesn't exist");
+ return false;
+ }
+ const smart_objects::SmartObject& ttsNameObject =
+ language[language_name][json::ttsName];
+ // ttsName is string
+ if (smart_objects::SmartType_String == ttsNameObject.getType()) {
+ const std::string ttsName =
+ language[language_name][json::ttsName].asString();
+ if (ttsName.length() > kTtsNameLengthMax) {
+ LOG4CXX_WARN(logger_,
+ kQueryAppsValidationFailedPrefix
+ << "ttsName string exceeds max length ["
+ << ttsName.length() << "]>[" << kTtsNameLengthMax
+ << "]");
+ return false;
+ }
+ } else {
+ LOG4CXX_WARN(logger_,
+ kQueryAppsValidationFailedPrefix
+ << "ttsName is not the string type.");
+ return false;
+ }
+
+ if (!ValidateSynonymsAtLanguage(language, language_name, synonyms_map)) {
+ return false;
+ }
+ }
+ if (!default_language_found) {
+ LOG4CXX_WARN(logger_,
+ kQueryAppsValidationFailedPrefix
+ << " 'languages'.default' doesn't exist");
+ return false;
+ }
+ return true;
+ }
+
+ bool ValidateSynonymsAtLanguage(const smart_objects::SmartObject& language,
+ const std::string& language_name,
+ SynonymsMap& synonyms_map) const {
+ if (!language[language_name].keyExists(json::vrSynonyms)) {
+ LOG4CXX_WARN(logger_,
+ kQueryAppsValidationFailedPrefix
+ << "'languages.vrSynonyms' doesn't exist");
+ return false;
+ }
+ const smart_objects::SmartArray* synonyms_array =
+ language[language_name][json::vrSynonyms].asArray();
+ if (!synonyms_array) {
+ LOG4CXX_WARN(logger_,
+ kQueryAppsValidationFailedPrefix
+ << "vrSynonyms is not array.");
+ return false;
+ }
+ const size_t synonyms_array_size = synonyms_array->size();
+ if (synonyms_array_size < kVrArraySizeMin) {
+ LOG4CXX_WARN(logger_,
+ kQueryAppsValidationFailedPrefix
+ << "vrSynomyms array has [" << synonyms_array_size
+ << "] size < allowed min size [" << kVrArraySizeMin
+ << "]");
+ return false;
+ }
+ if (synonyms_array_size > kVrArraySizeMax) {
+ LOG4CXX_WARN(logger_,
+ kQueryAppsValidationFailedPrefix
+ << "vrSynomyms array size [" << synonyms_array_size
+ << "] exceeds maximum allowed size [" << kVrArraySizeMax
+ << "]");
+ return false;
+ }
+
+ for (std::size_t idx = 0; idx < synonyms_array_size; ++idx) {
+ const smart_objects::SmartObject& synonym = (*synonyms_array)[idx];
+ const std::string vrSynonym = synonym.asString();
+ if (vrSynonym.length() > kVrSynonymLengthMax) {
+ LOG4CXX_WARN(logger_,
+ kQueryAppsValidationFailedPrefix
+ << "vrSYnomym item [" << idx
+ << "] exceeds max length [" << vrSynonym.length()
+ << "]>[" << kVrSynonymLengthMax << "]");
+ return false;
+ }
+ if (vrSynonym.length() < kVrSynonymLengthMin) {
+ LOG4CXX_WARN(logger_,
+ kQueryAppsValidationFailedPrefix
+ << "vrSYnomym item [" << idx << "] length ["
+ << vrSynonym.length() << "] is less then min length ["
+ << kVrSynonymLengthMin << "] allowed.");
+ return false;
+ }
+ // Verify duplicates
+ SynonymsMap::iterator synonyms_map_iter =
+ synonyms_map.find(language_name);
+ if (synonyms_map_iter != synonyms_map.end()) {
+ if (!(*synonyms_map_iter).second.insert(vrSynonym).second) {
+ LOG4CXX_WARN(logger_,
+ kQueryAppsValidationFailedPrefix
+ << "vrSYnomym item already defined ["
+ << vrSynonym.c_str() << "] for language ["
+ << language_name << "]");
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ const smart_objects::SmartObject& data_;
+ const ApplicationManagerImpl& manager_;
+
+ DISALLOW_COPY_AND_ASSIGN(QueryAppsDataValidator);
+};
+}
+
namespace commands {
uint32_t SystemRequest::index = 0;
@@ -174,9 +537,8 @@ void SystemRequest::Run() {
}
CFormatterJsonBase::jsonValueToObj(root, sm_object);
-
if (!ValidateQueryAppData(sm_object)) {
- SendResponse(false, mobile_apis::Result::INVALID_DATA);
+ SendResponse(false, mobile_apis::Result::GENERIC_ERROR);
return;
}
@@ -246,61 +608,23 @@ void SystemRequest::on_event(const event_engine::Event& event) {
bool SystemRequest::ValidateQueryAppData(
const smart_objects::SmartObject& data) const {
if (!data.isValid()) {
- LOG4CXX_ERROR(logger_, "QueryApps response is not valid.");
+ LOG4CXX_ERROR(logger_,
+ kQueryAppsValidationFailedPrefix
+ << "QueryApps response is not valid.");
return false;
}
if (!data.keyExists(json::response)) {
LOG4CXX_ERROR(logger_,
- "QueryApps response does not contain '" << json::response
- << "' parameter.");
+ kQueryAppsValidationFailedPrefix
+ << "QueryApps response does not contain '"
+ << json::response << "' parameter.");
return false;
}
- smart_objects::SmartArray* obj_array = data[json::response].asArray();
- if (NULL == obj_array) {
- return false;
- }
-
- const std::size_t arr_size(obj_array->size());
- for (std::size_t idx = 0; idx < arr_size; ++idx) {
- const smart_objects::SmartObject& app_data = (*obj_array)[idx];
- if (!app_data.isValid()) {
- LOG4CXX_ERROR(logger_, "Wrong application data in json file.");
- continue;
- }
- std::string os_type;
- if (app_data.keyExists(json::ios)) {
- os_type = json::ios;
- if (!app_data[os_type].keyExists(json::urlScheme)) {
- LOG4CXX_ERROR(logger_, "Can't find URL scheme in json file.");
- continue;
- }
- } else if (app_data.keyExists(json::android)) {
- os_type = json::android;
- if (!app_data[os_type].keyExists(json::packageName)) {
- LOG4CXX_ERROR(logger_, "Can't find package name in json file.");
- continue;
- }
- }
-
- if (os_type.empty()) {
- LOG4CXX_ERROR(logger_, "Can't find mobile OS type in json file.");
- continue;
- }
-
- if (!app_data.keyExists(json::appId)) {
- LOG4CXX_ERROR(logger_, "Can't find app ID in json file.");
- continue;
- }
-
- if (!app_data.keyExists(json::name)) {
- LOG4CXX_ERROR(logger_, "Can't find app name in json file.");
- continue;
- }
-
- return true;
- }
+ ApplicationManagerImpl* manager = ApplicationManagerImpl::instance();
+ DCHECK(manager);
- return false;
+ QueryAppsDataValidator validator(data, *manager);
+ return validator.Validate();
}
} // namespace commands
diff --git a/src/components/application_manager/src/hmi_command_factory.cc b/src/components/application_manager/src/hmi_command_factory.cc
index 5701c67b4a..31c8923790 100644
--- a/src/components/application_manager/src/hmi_command_factory.cc
+++ b/src/components/application_manager/src/hmi_command_factory.cc
@@ -262,13 +262,14 @@
#include "application_manager/commands/hmi/navi_send_location_request.h"
#include "application_manager/commands/hmi/navi_send_location_response.h"
#include "application_manager/commands/hmi/on_tts_reset_timeout_notification.h"
+#include "application_manager/commands/hmi/on_phone_call_notification.h"
#include "application_manager/commands/hmi/dial_number_request.h"
#include "application_manager/commands/hmi/dial_number_response.h"
-CREATE_LOGGERPTR_GLOBAL(logger_, "ApplicationManager")
-
namespace application_manager {
+CREATE_LOGGERPTR_GLOBAL(logger_, "ApplicationManager")
+
CommandSharedPtr HMICommandFactory::CreateCommand(
const commands::MessageSharedPtr& message) {
const int function_id = (*message)[strings::params][strings::function_id]
@@ -2048,6 +2049,10 @@ CommandSharedPtr HMICommandFactory::CreateCommand(
command.reset(new commands::hmi::OnTTSResetTimeoutNotification(message));
break;
}
+ case hmi_apis::FunctionID::BasicCommunication_OnEventChanged: {
+ command.reset(new commands::OnEventChangedNotification(message));
+ break;
+ }
case hmi_apis::FunctionID::BasicCommunication_DialNumber: {
if (is_response) {
command.reset(new commands::hmi::DialNumberResponse(message));
@@ -2056,10 +2061,6 @@ CommandSharedPtr HMICommandFactory::CreateCommand(
}
break;
}
- case hmi_apis::FunctionID::BasicCommunication_OnEventChanged: {
- command.reset(new commands::OnEventChangedNotification(message));
- break;
- }
}
return command;
diff --git a/src/components/application_manager/src/mobile_command_factory.cc b/src/components/application_manager/src/mobile_command_factory.cc
index ff2d4fd49e..3399ec2667 100644
--- a/src/components/application_manager/src/mobile_command_factory.cc
+++ b/src/components/application_manager/src/mobile_command_factory.cc
@@ -489,6 +489,15 @@ CommandSharedPtr MobileCommandFactory::CreateCommand(
}
break;
}
+ case mobile_apis::FunctionID::DialNumberID: {
+ if ((*message)[strings::params][strings::message_type]
+ == static_cast<int>(application_manager::MessageType::kResponse)) {
+ return new commands::DialNumberResponse(message);
+ } else {
+ return new commands::DialNumberRequest(message);
+ }
+ break;
+ }
case mobile_apis::FunctionID::OnButtonEventID: {
command = utils::MakeShared<commands::mobile::OnButtonEventNotification>(message);
break;
diff --git a/src/components/interfaces/HMI_API.xml b/src/components/interfaces/HMI_API.xml
index f16dc972dc..1762018e98 100644
--- a/src/components/interfaces/HMI_API.xml
+++ b/src/components/interfaces/HMI_API.xml
@@ -2205,10 +2205,20 @@
<description>ID of application that concerns this RPC.</description>
</param>
</function>
+ <function name="DialNumber" messagetype="request">
+ <description>Request from SDL to call a specific number.</description>
+ <param name="number" type="String" maxlength="40">
+ <description>Phone number is a string, which can be up to 40 chars.
+ All characters shall be stripped from string except digits 0-9 and * # , ; +
+ </description>
+ </param>
+ <param name="appID" type="Integer" mandatory="true">
+ <description>ID of application that concerns this RPC.</description>
+ </param>
+ </function>
<function name="DialNumber" messagetype="response">
</function>
-
<!-- Policies -->
<!-- SyncP RPC-->