APPLINK-6400:
[profile/ivi/smartdevicelink.git] / src / components / application_manager / src / application_manager_impl.cc
1 /**
2  * Copyright (c) 2013, Ford Motor Company
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * Redistributions of source code must retain the above copyright notice, this
9  * list of conditions and the following disclaimer.
10  *
11  * Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following
13  * disclaimer in the documentation and/or other materials provided with the
14  * distribution.
15  *
16  * Neither the name of the Ford Motor Company nor the names of its contributors
17  * may be used to endorse or promote products derived from this software
18  * without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
24  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 #include "application_manager/application_manager_impl.h"
34
35 #include <climits>
36 #include <string>
37 #include <fstream>
38
39 #include "application_manager/application_manager_impl.h"
40 #include "application_manager/mobile_command_factory.h"
41 #include "application_manager/commands/command_impl.h"
42 #include "application_manager/commands/command_notification_impl.h"
43 #include "application_manager/message_helper.h"
44 #include "application_manager/mobile_message_handler.h"
45 #include "application_manager/policies/policy_handler.h"
46 #include "connection_handler/connection_handler_impl.h"
47 #include "formatters/formatter_json_rpc.h"
48 #include "formatters/CFormatterJsonSDLRPCv2.hpp"
49 #include "formatters/CFormatterJsonSDLRPCv1.hpp"
50 #include "config_profile/profile.h"
51 #include "utils/threads/thread.h"
52 #include "utils/file_system.h"
53 #include "application_manager/application_impl.h"
54 #include "usage_statistics/counter.h"
55
56 namespace application_manager {
57
58 #ifdef ENABLE_LOG
59 log4cxx::LoggerPtr ApplicationManagerImpl::logger_ = log4cxx::LoggerPtr(
60     log4cxx::Logger::getLogger("ApplicationManager"));
61 #endif // ENABLE_LOG
62
63 uint32_t ApplicationManagerImpl::corelation_id_ = 0;
64 const uint32_t ApplicationManagerImpl::max_corelation_id_ = UINT_MAX;
65
66 namespace formatters = NsSmartDeviceLink::NsJSONHandler::Formatters;
67 namespace jhs = NsSmartDeviceLink::NsJSONHandler::strings;
68
69 ApplicationManagerImpl::ApplicationManagerImpl()
70   : audio_pass_thru_active_(false),
71     is_distracting_driver_(false),
72     is_vr_session_strated_(false),
73     hmi_cooperating_(false),
74     is_all_apps_allowed_(true),
75     hmi_handler_(NULL),
76     connection_handler_(NULL),
77     policy_manager_(NULL),
78     hmi_so_factory_(NULL),
79     mobile_so_factory_(NULL),
80     protocol_handler_(NULL),
81     messages_from_mobile_("application_manager::FromMobileThreadImpl", this),
82     messages_to_mobile_("application_manager::ToMobileThreadImpl", this),
83     messages_from_hmi_("application_manager::FromHMHThreadImpl", this),
84     messages_to_hmi_("application_manager::ToHMHThreadImpl", this),
85     request_ctrl_(),
86     hmi_capabilities_(this),
87     unregister_reason_(mobile_api::AppInterfaceUnregisteredReason::IGNITION_OFF),
88     media_manager_(NULL),
89     resume_ctrl_(this) {
90   LOG4CXX_INFO(logger_, "Creating ApplicationManager");
91   media_manager_ = media_manager::MediaManagerImpl::instance();
92   CreatePoliciesManager();
93 }
94
95 bool ApplicationManagerImpl::InitThread(threads::Thread* thread) {
96   if (!thread) {
97     LOG4CXX_ERROR(logger_, "Failed to allocate memory for thread object");
98     return false;
99   }
100   LOG4CXX_INFO(
101     logger_,
102     "Starting thread with stack size "
103     << profile::Profile::instance()->thread_min_stack_size());
104   if (!thread->start()) {
105     /*startWithOptions(
106      threads::ThreadOptions(
107      profile::Profile::instance()->thread_min_stack_size()))*/
108     LOG4CXX_ERROR(logger_, "Failed to start thread");
109     return false;
110   }
111   return true;
112 }
113
114 ApplicationManagerImpl::~ApplicationManagerImpl() {
115   LOG4CXX_INFO(logger_, "Destructing ApplicationManager.");
116
117   if (policy_manager_) {
118     LOG4CXX_INFO(logger_, "Unloading policy library.");
119     policy::PolicyHandler::instance()->UnloadPolicyLibrary();
120   }
121   policy_manager_ = NULL;
122   media_manager_ = NULL;
123   hmi_handler_ = NULL;
124   connection_handler_ = NULL;
125   hmi_so_factory_ = NULL;
126   mobile_so_factory_ = NULL;
127   protocol_handler_ = NULL;
128   media_manager_ = NULL;
129 }
130
131 bool ApplicationManagerImpl::Stop() {
132   LOG4CXX_INFO(logger_, "Stop ApplicationManager.");
133   try {
134     UnregisterAllApplications();
135   } catch (...) {
136     LOG4CXX_ERROR(logger_,
137                   "An error occured during unregistering applications.");
138   }
139   MessageHelper::SendOnSdlCloseNotificationToHMI();
140   return true;
141 }
142
143 ApplicationSharedPtr ApplicationManagerImpl::application(int32_t app_id) const {
144   sync_primitives::AutoLock lock(applications_list_lock_);
145
146   std::map<int32_t, ApplicationSharedPtr>::const_iterator it =
147     applications_.find(app_id);
148   if (applications_.end() != it) {
149     return it->second;
150   } else {
151     return ApplicationSharedPtr();
152   }
153 }
154
155 ApplicationSharedPtr ApplicationManagerImpl::active_application() const {
156   // TODO(DK) : check driver distraction
157   for (std::set<ApplicationSharedPtr>::iterator it = application_list_.begin();
158        application_list_.end() != it;
159        ++it) {
160     if ((*it)->IsFullscreen()) {
161       return *it;
162     }
163   }
164   return ApplicationSharedPtr();
165 }
166
167 std::vector<ApplicationSharedPtr> ApplicationManagerImpl::applications_by_button(
168   uint32_t button) {
169   std::vector<ApplicationSharedPtr> result;
170   for (std::set<ApplicationSharedPtr>::iterator it = application_list_.begin();
171        application_list_.end() != it; ++it) {
172     if ((*it)->IsSubscribedToButton(
173           static_cast<mobile_apis::ButtonName::eType>(button))) {
174       result.push_back(*it);
175     }
176   }
177   return result;
178 }
179
180 std::vector<utils::SharedPtr<Application>> ApplicationManagerImpl::IviInfoUpdated(
181 VehicleDataType vehicle_info, int value) {
182   // Notify Policy Manager if available about info it's interested in,
183   // i.e. odometer etc
184   switch (vehicle_info) {
185     case ODOMETER:
186       policy::PolicyHandler::instance()->KmsChanged(value);
187       break;
188     default:
189       break;
190   }
191
192   std::vector<utils::SharedPtr<application_manager::Application>> result;
193   for (std::set<utils::SharedPtr<application_manager::Application>>::iterator it = application_list_.begin();
194        application_list_.end() != it; ++it) {
195     if ((*it)->IsSubscribedToIVI(static_cast<uint32_t>(vehicle_info))) {
196       result.push_back(*it);
197     }
198   }
199   return result;
200 }
201
202 std::vector<ApplicationSharedPtr> ApplicationManagerImpl::applications_with_navi() {
203   std::vector<ApplicationSharedPtr> result;
204   for (std::set<ApplicationSharedPtr>::iterator it = application_list_.begin();
205        application_list_.end() != it;
206        ++it) {
207     if ((*it)->allowed_support_navigation()) {
208       result.push_back(*it);
209     }
210   }
211   return result;
212 }
213
214 ApplicationSharedPtr ApplicationManagerImpl::RegisterApplication(
215   const utils::SharedPtr<smart_objects::SmartObject>&
216   request_for_registration) {
217   smart_objects::SmartObject& message = *request_for_registration;
218   uint32_t connection_key =
219     message[strings::params][strings::connection_key].asInt();
220
221   if (false == is_all_apps_allowed_) {
222     LOG4CXX_INFO(logger_,
223                  "RegisterApplication: access to app's disabled by user");
224     utils::SharedPtr<smart_objects::SmartObject> response(
225       MessageHelper::CreateNegativeResponse(
226         connection_key, mobile_apis::FunctionID::RegisterAppInterfaceID,
227         message[strings::params][strings::correlation_id].asUInt(),
228         mobile_apis::Result::DISALLOWED));
229     ManageMobileCommand(response);
230     return ApplicationSharedPtr();
231   }
232
233   // app_id is SDL "internal" ID
234   // original app_id can be gotten via ApplicationImpl::mobile_app_id()
235   uint32_t app_id = 0;
236   std::list<int32_t> sessions_list;
237   uint32_t device_id = 0;
238
239   if (connection_handler_) {
240     connection_handler::ConnectionHandlerImpl* con_handler_impl =
241       static_cast<connection_handler::ConnectionHandlerImpl*>(
242         connection_handler_);
243     if (con_handler_impl->GetDataOnSessionKey(connection_key, &app_id,
244         &sessions_list, &device_id)
245         == -1) {
246       LOG4CXX_ERROR(logger_,
247                     "Failed to create application: no connection info.");
248       utils::SharedPtr<smart_objects::SmartObject> response(
249         MessageHelper::CreateNegativeResponse(
250           connection_key, mobile_apis::FunctionID::RegisterAppInterfaceID,
251           message[strings::params][strings::correlation_id].asUInt(),
252           mobile_apis::Result::GENERIC_ERROR));
253       ManageMobileCommand(response);
254       return ApplicationSharedPtr();
255     }
256   }
257
258   smart_objects::SmartObject& params = message[strings::msg_params];
259
260   const std::string mobile_app_id = params[strings::app_id].asString();
261   ApplicationSharedPtr application(
262       new ApplicationImpl(app_id, mobile_app_id, policy_manager_));
263   if (!application) {
264     usage_statistics::AppCounter count_of_rejections_sync_out_of_memory(
265         policy_manager_, mobile_app_id,
266         usage_statistics::REJECTIONS_SYNC_OUT_OF_MEMORY);
267     ++count_of_rejections_sync_out_of_memory;
268
269     utils::SharedPtr<smart_objects::SmartObject> response(
270       MessageHelper::CreateNegativeResponse(
271         connection_key, mobile_apis::FunctionID::RegisterAppInterfaceID,
272         message[strings::params][strings::correlation_id].asUInt(),
273         mobile_apis::Result::OUT_OF_MEMORY));
274     ManageMobileCommand(response);
275     return ApplicationSharedPtr();
276   }
277
278   const std::string& name =
279     message[strings::msg_params][strings::app_name].asString();
280
281   application->set_name(name);
282   application->set_device(device_id);
283
284   mobile_api::Language::eType launguage_desired =
285       static_cast<mobile_api::Language::eType>(params[strings::language_desired]
286           .asInt());
287   application->set_language(launguage_desired);
288   application->usage_report().RecordAppRegistrationVuiLanguage(
289       launguage_desired);
290
291   mobile_api::Language::eType hmi_display_language_desired =
292       static_cast<mobile_api::Language::eType>(params[strings::hmi_display_language_desired]
293           .asInt());
294   application->set_ui_language(hmi_display_language_desired);
295   application->usage_report().RecordAppRegistrationGuiLanguage(
296       hmi_display_language_desired);
297
298   Version version;
299   int32_t min_version =
300     message[strings::msg_params][strings::sync_msg_version]
301     [strings::minor_version].asInt();
302
303   /*if (min_version < APIVersion::kAPIV2) {
304     LOG4CXX_ERROR(logger_, "UNSUPPORTED_VERSION");
305     utils::SharedPtr<smart_objects::SmartObject> response(
306       MessageHelper::CreateNegativeResponse(
307         connection_key, mobile_apis::FunctionID::RegisterAppInterfaceID,
308         message[strings::params][strings::correlation_id],
309         mobile_apis::Result::UNSUPPORTED_VERSION));
310     ManageMobileCommand(response);
311     delete application;
312     return NULL;
313   }*/
314   version.min_supported_api_version = static_cast<APIVersion>(min_version);
315
316   int32_t max_version =
317     message[strings::msg_params][strings::sync_msg_version]
318     [strings::major_version].asInt();
319
320   /*if (max_version > APIVersion::kAPIV2) {
321     LOG4CXX_ERROR(logger_, "UNSUPPORTED_VERSION");
322     utils::SharedPtr<smart_objects::SmartObject> response(
323       MessageHelper::CreateNegativeResponse(
324         connection_key, mobile_apis::FunctionID::RegisterAppInterfaceID,
325         message[strings::params][strings::correlation_id],
326         mobile_apis::Result::UNSUPPORTED_VERSION));
327     ManageMobileCommand(response);
328     delete application;
329     return NULL;
330   }*/
331   version.max_supported_api_version = static_cast<APIVersion>(max_version);
332   application->set_version(version);
333
334   application->set_mobile_app_id(message[strings::msg_params][strings::app_id]);
335
336   sync_primitives::AutoLock lock(applications_list_lock_);
337
338   applications_.insert(std::pair<int32_t, ApplicationSharedPtr>(app_id, application));
339   application_list_.insert(application);
340
341   // TODO(PV): add asking user to allow application
342   // BasicCommunication_AllowApp
343   // application->set_app_allowed(result);
344   return application;
345 }
346
347 bool ApplicationManagerImpl::RemoveAppDataFromHMI(ApplicationSharedPtr app) {
348   return true;
349 }
350
351 bool ApplicationManagerImpl::LoadAppDataToHMI(ApplicationSharedPtr app) {
352   return true;
353 }
354
355 bool ApplicationManagerImpl::ActivateApplication(ApplicationSharedPtr app) {
356   if (!app) {
357     LOG4CXX_ERROR(logger_, "Null-pointer application received.");
358     NOTREACHED();
359     return false;
360   }
361
362   bool is_new_app_media = app->is_media_application();
363
364   for (std::set<ApplicationSharedPtr>::iterator it = application_list_.begin();
365        application_list_.end() != it;
366        ++it) {
367     ApplicationSharedPtr curr_app = *it;
368     if (app->app_id() == curr_app->app_id()) {
369       if (curr_app->IsFullscreen()) {
370         LOG4CXX_WARN(logger_, "Application is already active.");
371         return false;
372       }
373       if (mobile_api::HMILevel::eType::HMI_LIMITED !=
374           curr_app->hmi_level()) {
375         if (curr_app->has_been_activated()) {
376           MessageHelper::SendAppDataToHMI(curr_app);
377         }
378       }
379       if (!curr_app->MakeFullscreen()) {
380         return false;
381       }
382       MessageHelper::SendHMIStatusNotification(*curr_app);
383     } else {
384       if (is_new_app_media) {
385         if (curr_app->IsAudible()) {
386           curr_app->MakeNotAudible();
387           MessageHelper::SendHMIStatusNotification(*curr_app);
388         }
389       }
390       if (curr_app->IsFullscreen()) {
391         MessageHelper::RemoveAppDataFromHMI(curr_app);
392       }
393     }
394   }
395   return true;
396 }
397
398 mobile_apis::HMILevel::eType ApplicationManagerImpl::PutApplicationInLimited(
399   ApplicationSharedPtr app) {
400   DCHECK(app.get())
401
402   bool is_new_app_media = app->is_media_application();
403   mobile_api::HMILevel::eType result = mobile_api::HMILevel::HMI_LIMITED;
404
405   for (std::set<ApplicationSharedPtr>::iterator it = application_list_.begin();
406        application_list_.end() != it;
407        ++it) {
408     ApplicationSharedPtr curr_app = *it;
409     if (app->app_id() == curr_app->app_id()) {
410       continue;
411     }
412
413     if (curr_app->hmi_level() == mobile_api::HMILevel::HMI_LIMITED) {
414       result = mobile_api::HMILevel::HMI_BACKGROUND;
415       break;
416     }
417     if (curr_app->hmi_level() == mobile_api::HMILevel::HMI_FULL) {
418       if (curr_app->is_media_application()) {
419         result = mobile_api::HMILevel::HMI_BACKGROUND;
420         break;
421       } else {
422         result = mobile_api::HMILevel::HMI_LIMITED;
423       }
424     }
425
426   }
427   app->set_hmi_level(result);
428   return result;
429 }
430
431 mobile_api::HMILevel::eType ApplicationManagerImpl::PutApplicationInFull(
432   ApplicationSharedPtr app) {
433   DCHECK(app.get())
434
435   bool is_new_app_media = app->is_media_application();
436   mobile_api::HMILevel::eType result = mobile_api::HMILevel::HMI_FULL;
437
438   std::set<ApplicationSharedPtr>::iterator it = application_list_.begin();
439   for (; application_list_.end() != it; ++it) {
440     ApplicationSharedPtr curr_app = *it;
441     if (app->app_id() == curr_app->app_id()) {
442       continue;
443     }
444
445     if (is_new_app_media) {
446       if (curr_app->hmi_level() == mobile_api::HMILevel::HMI_FULL) {
447         if (curr_app->is_media_application()) {
448           result = mobile_api::HMILevel::HMI_BACKGROUND;
449           break;
450         } else {
451           result = mobile_api::HMILevel::HMI_LIMITED;
452         }
453       }
454       if (curr_app->hmi_level() == mobile_api::HMILevel::HMI_LIMITED) {
455         result = mobile_api::HMILevel::HMI_BACKGROUND;
456         break;
457       }
458     } else {
459       if (curr_app->hmi_level() == mobile_api::HMILevel::HMI_FULL) {
460         result = mobile_api::HMILevel::HMI_BACKGROUND;
461         break;
462       }
463       if (curr_app->hmi_level() == mobile_api::HMILevel::HMI_LIMITED) {
464         result = mobile_api::HMILevel::HMI_FULL;
465       }
466     }
467   }
468
469   if (result == mobile_api::HMILevel::HMI_FULL) {
470     app->set_hmi_level(result);
471     MessageHelper::SendActivateAppToHMI(app->app_id());
472   }
473   return result;
474 }
475
476 void ApplicationManagerImpl::DeactivateApplication(ApplicationSharedPtr app) {
477   MessageHelper::SendDeleteCommandRequestToHMI(app);
478   MessageHelper::ResetGlobalproperties(app);
479 }
480
481 void ApplicationManagerImpl::ConnectToDevice(uint32_t id) {
482   // TODO(VS): Call function from ConnectionHandler
483   if (!connection_handler_) {
484     LOG4CXX_WARN(logger_, "Connection handler is not set.");
485     return;
486   }
487
488   connection_handler_->ConnectToDevice(id);
489 }
490
491 void ApplicationManagerImpl::OnHMIStartedCooperation() {
492   hmi_cooperating_ = true;
493   LOG4CXX_INFO(logger_, "ApplicationManagerImpl::OnHMIStartedCooperation()");
494
495   if (true == profile::Profile::instance()->launch_hmi()) {
496     utils::SharedPtr<smart_objects::SmartObject> is_vr_ready(
497       MessageHelper::CreateModuleInfoSO(
498         static_cast<uint32_t>(hmi_apis::FunctionID::VR_IsReady)));
499     ManageHMICommand(is_vr_ready);
500
501     utils::SharedPtr<smart_objects::SmartObject> is_tts_ready(
502       MessageHelper::CreateModuleInfoSO(hmi_apis::FunctionID::TTS_IsReady));
503     ManageHMICommand(is_tts_ready);
504
505     utils::SharedPtr<smart_objects::SmartObject> is_ui_ready(
506       MessageHelper::CreateModuleInfoSO(hmi_apis::FunctionID::UI_IsReady));
507     ManageHMICommand(is_ui_ready);
508
509     utils::SharedPtr<smart_objects::SmartObject> is_navi_ready(
510       MessageHelper::CreateModuleInfoSO(
511         hmi_apis::FunctionID::Navigation_IsReady));
512     ManageHMICommand(is_navi_ready);
513
514     utils::SharedPtr<smart_objects::SmartObject> is_ivi_ready(
515       MessageHelper::CreateModuleInfoSO(
516         hmi_apis::FunctionID::VehicleInfo_IsReady));
517     ManageHMICommand(is_ivi_ready);
518
519     utils::SharedPtr<smart_objects::SmartObject> button_capabilities(
520       MessageHelper::CreateModuleInfoSO(
521         hmi_apis::FunctionID::Buttons_GetCapabilities));
522     ManageHMICommand(button_capabilities);
523   }
524
525   if (!connection_handler_) {
526     LOG4CXX_WARN(logger_, "Connection handler is not set.");
527   } else {
528     connection_handler_->StartTransportManager();
529   }
530 }
531
532 uint32_t ApplicationManagerImpl::GetNextHMICorrelationID() {
533   if (corelation_id_ < max_corelation_id_) {
534     corelation_id_++;
535   } else {
536     corelation_id_ = 0;
537   }
538
539   return corelation_id_;
540 }
541
542 bool ApplicationManagerImpl::begin_audio_pass_thru() {
543   sync_primitives::AutoLock lock(audio_pass_thru_lock_);
544   if (audio_pass_thru_active_) {
545     return false;
546   } else {
547     audio_pass_thru_active_ = true;
548     return true;
549   }
550 }
551
552 bool ApplicationManagerImpl::end_audio_pass_thru() {
553   sync_primitives::AutoLock lock(audio_pass_thru_lock_);
554   if (audio_pass_thru_active_) {
555     audio_pass_thru_active_ = false;
556     return true;
557   } else {
558     return false;
559   }
560 }
561
562 void ApplicationManagerImpl::set_driver_distraction(bool is_distracting) {
563   is_distracting_driver_ = is_distracting;
564 }
565
566 void ApplicationManagerImpl::set_vr_session_started(const bool& state) {
567   is_vr_session_strated_ = state;
568 }
569
570 void ApplicationManagerImpl::set_all_apps_allowed(const bool& allowed) {
571   is_all_apps_allowed_ = allowed;
572 }
573
574 void ApplicationManagerImpl::StartAudioPassThruThread(int32_t session_key,
575     int32_t correlation_id, int32_t max_duration, int32_t sampling_rate,
576     int32_t bits_per_sample, int32_t audio_type) {
577   LOG4CXX_INFO(logger_, "START MICROPHONE RECORDER");
578   if (NULL != media_manager_) {
579     media_manager_->StartMicrophoneRecording(
580       session_key,
581       std::string("record.wav"),
582       max_duration);
583   }
584 }
585
586 void ApplicationManagerImpl::SendAudioPassThroughNotification(
587   uint32_t session_key,
588   std::vector<uint8_t> binaryData) {
589   LOG4CXX_TRACE_ENTER(logger_);
590
591   {
592     sync_primitives::AutoLock lock(audio_pass_thru_lock_);
593     if (!audio_pass_thru_active_) {
594       LOG4CXX_ERROR(logger_, "Trying to send PassThroughNotification"
595                     " when PassThrough is not active");
596
597       return;
598     }
599   }
600
601   smart_objects::SmartObject* on_audio_pass = NULL;
602   on_audio_pass = new smart_objects::SmartObject();
603
604   if (NULL == on_audio_pass) {
605     LOG4CXX_ERROR_EXT(logger_, "OnAudioPassThru NULL pointer");
606
607     return;
608   }
609
610   LOG4CXX_INFO_EXT(logger_, "Fill smart object");
611
612   (*on_audio_pass)[strings::params][strings::message_type] =
613     application_manager::MessageType::kNotification;
614
615   (*on_audio_pass)[strings::params][strings::connection_key] =
616     static_cast<int32_t>(session_key);
617   (*on_audio_pass)[strings::params][strings::function_id] =
618     mobile_apis::FunctionID::OnAudioPassThruID;
619
620   LOG4CXX_INFO_EXT(logger_, "Fill binary data");
621   // binary data
622   (*on_audio_pass)[strings::params][strings::binary_data] =
623     smart_objects::SmartObject(binaryData);
624
625   LOG4CXX_INFO_EXT(logger_, "After fill binary data");
626
627   LOG4CXX_INFO_EXT(logger_, "Send data");
628   CommandSharedPtr command =
629     MobileCommandFactory::CreateCommand(&(*on_audio_pass));
630   command->Init();
631   command->Run();
632   command->CleanUp();
633 }
634
635 void ApplicationManagerImpl::StopAudioPassThru(int32_t application_key) {
636   LOG4CXX_TRACE_ENTER(logger_);
637   if (NULL != media_manager_) {
638     media_manager_->StopMicrophoneRecording(application_key);
639   }
640 }
641
642 std::string ApplicationManagerImpl::GetDeviceName(
643   connection_handler::DeviceHandle handle) {
644   DCHECK(connection_handler_ != 0);
645
646   std::string device_name = "";
647   std::list<uint32_t> applications_list;
648   connection_handler::ConnectionHandlerImpl* con_handler_impl =
649     static_cast<connection_handler::ConnectionHandlerImpl*>(
650       connection_handler_);
651   if (con_handler_impl->GetDataOnDeviceID(handle, &device_name,
652                                           &applications_list) == -1) {
653     LOG4CXX_ERROR(logger_, "Failed to extract device name for id " << handle);
654   } else {
655     LOG4CXX_INFO(logger_, "\t\t\t\t\tDevice name is " << device_name);
656   }
657
658   return device_name;
659 }
660
661 void ApplicationManagerImpl::OnMessageReceived(
662   const protocol_handler::RawMessagePtr& message) {
663   LOG4CXX_INFO(logger_, "ApplicationManagerImpl::OnMessageReceived");
664
665   if (!message) {
666     LOG4CXX_ERROR(logger_, "Null-pointer message received.");
667     NOTREACHED();
668     return;
669   }
670
671   utils::SharedPtr<Message> outgoing_message = ConvertRawMsgToMessage(message);
672   if (outgoing_message) {
673     messages_from_mobile_.PostMessage(
674       impl::MessageFromMobile(outgoing_message));
675   } else {
676     LOG4CXX_WARN(logger_, "Incorrect message received");
677   }
678 }
679
680 void ApplicationManagerImpl::OnMobileMessageSent(
681   const protocol_handler::RawMessagePtr& message) {
682   LOG4CXX_INFO(logger_, "ApplicationManagerImpl::OnMobileMessageSent");
683 }
684
685 void ApplicationManagerImpl::OnMessageReceived(
686   hmi_message_handler::MessageSharedPointer message) {
687   LOG4CXX_INFO(logger_, "ApplicationManagerImpl::OnMessageReceived");
688
689   if (!message) {
690     LOG4CXX_ERROR(logger_, "Null-pointer message received.");
691     NOTREACHED();
692     return;
693   }
694
695   messages_from_hmi_.PostMessage(impl::MessageFromHmi(message));
696 }
697
698 void ApplicationManagerImpl::OnErrorSending(
699   hmi_message_handler::MessageSharedPointer message) {
700   return;
701 }
702
703 void ApplicationManagerImpl::OnDeviceListUpdated(
704   const connection_handler::DeviceList& device_list) {
705   LOG4CXX_INFO(logger_, "ApplicationManagerImpl::OnDeviceListUpdated");
706
707   smart_objects::SmartObject* update_list = new smart_objects::SmartObject;
708   smart_objects::SmartObject& so_to_send = *update_list;
709   so_to_send[jhs::S_PARAMS][jhs::S_FUNCTION_ID] =
710     hmi_apis::FunctionID::BasicCommunication_UpdateDeviceList;
711   so_to_send[jhs::S_PARAMS][jhs::S_MESSAGE_TYPE] =
712     hmi_apis::messageType::request;
713   so_to_send[jhs::S_PARAMS][jhs::S_PROTOCOL_VERSION] = 2;
714   so_to_send[jhs::S_PARAMS][jhs::S_PROTOCOL_TYPE] = 1;
715   so_to_send[jhs::S_PARAMS][jhs::S_CORRELATION_ID] = GetNextHMICorrelationID();
716   smart_objects::SmartObject* msg_params = MessageHelper::CreateDeviceListSO(
717         device_list);
718   if (!msg_params) {
719     LOG4CXX_WARN(logger_, "Failed to create sub-smart object.");
720     delete update_list;
721     return;
722   }
723   so_to_send[jhs::S_MSG_PARAMS] = *msg_params;
724   ManageHMICommand(update_list);
725 }
726
727 void ApplicationManagerImpl::RemoveDevice(
728   const connection_handler::DeviceHandle& device_handle) {
729 }
730
731
732 bool ApplicationManagerImpl::IsAudioStreamingAllowed(uint32_t connection_key) const {
733   ApplicationSharedPtr app = application(connection_key);
734
735   if (!app) {
736     LOG4CXX_INFO(logger_, "An application is not registered.");
737     return false;
738   }
739
740   const mobile_api::HMILevel::eType& hmi_level = app->hmi_level();
741
742   if (mobile_api::HMILevel::HMI_FULL == hmi_level ||
743       mobile_api::HMILevel::HMI_LIMITED == hmi_level) {
744     return true;
745   }
746
747   return false;
748 }
749
750 bool ApplicationManagerImpl::IsVideoStreamingAllowed(uint32_t connection_key) const {
751   ApplicationSharedPtr app = application(connection_key);
752
753   if (!app) {
754     LOG4CXX_INFO(logger_, "An application is not registered.");
755     return false;
756   }
757
758   const mobile_api::HMILevel::eType& hmi_level = app->hmi_level();
759
760   if (mobile_api::HMILevel::HMI_FULL == hmi_level &&
761       app->hmi_supports_navi_streaming()) {
762     return true;
763   }
764
765   return false;
766 }
767
768 bool ApplicationManagerImpl::OnServiceStartedCallback(
769   const connection_handler::DeviceHandle& device_handle,
770   const int32_t& session_key,
771   const protocol_handler::ServiceType& type) {
772   LOG4CXX_INFO(logger_,
773                "OnServiceStartedCallback " << type << " in session " << session_key);
774
775   ApplicationSharedPtr app = application(session_key);
776
777   switch (type) {
778     case protocol_handler::kRpc: {
779       LOG4CXX_INFO(logger_, "RPC service is about to be started.");
780       break;
781     }
782     case protocol_handler::kMobileNav: {
783       LOG4CXX_INFO(logger_, "Video service is about to be started.");
784       if (media_manager_) {
785         if (!app) {
786           LOG4CXX_ERROR_EXT(logger_, "An application is not registered.");
787           return false;
788         }
789         if (app->allowed_support_navigation()) {
790           media_manager_->StartVideoStreaming(session_key);
791         } else {
792           return false;
793         }
794       }
795       break;
796     }
797     case protocol_handler::kAudio: {
798       LOG4CXX_INFO(logger_, "Audio service is about to be started.");
799       if (media_manager_) {
800         if (!app) {
801           LOG4CXX_ERROR_EXT(logger_, "An application is not registered.");
802           return false;
803         }
804         if (app->allowed_support_navigation()) {
805           media_manager_->StartAudioStreaming(session_key);
806         } else {
807           return false;
808         }
809       }
810       break;
811     }
812     default: {
813       LOG4CXX_WARN(logger_, "Unknown type of service to be started.");
814       break;
815     }
816   }
817
818   return true;
819 }
820
821 void ApplicationManagerImpl::OnServiceEndedCallback(const int32_t& session_key,
822     const protocol_handler::ServiceType& type) {
823   LOG4CXX_INFO_EXT(
824     logger_,
825     "OnServiceEndedCallback " << type  << " in session " << session_key);
826   switch (type) {
827     case protocol_handler::kRpc: {
828       LOG4CXX_INFO(logger_, "Remove application.");
829       UnregisterApplication(session_key, mobile_apis::Result::INVALID_ENUM,
830                             true);
831       break;
832     }
833     case protocol_handler::kMobileNav: {
834       LOG4CXX_INFO(logger_, "Stop video streaming.");
835       if (media_manager_) {
836         media_manager_->StopVideoStreaming(session_key);
837       }
838       break;
839     }
840     case protocol_handler::kAudio: {
841       LOG4CXX_INFO(logger_, "Stop audio service.");
842       if (media_manager_) {
843         media_manager_->StopAudioStreaming(session_key);
844       }
845       break;
846     }
847     default:
848       LOG4CXX_WARN(logger_, "Unknown type of service to be ended.");
849       break;
850   }
851 }
852
853 void ApplicationManagerImpl::set_hmi_message_handler(
854   hmi_message_handler::HMIMessageHandler* handler) {
855   hmi_handler_ = handler;
856 }
857
858 void ApplicationManagerImpl::set_connection_handler(
859   connection_handler::ConnectionHandler* handler) {
860   connection_handler_ = handler;
861 }
862
863 void ApplicationManagerImpl::set_protocol_handler(
864   protocol_handler::ProtocolHandler* handler) {
865   protocol_handler_ = handler;
866 }
867
868 void ApplicationManagerImpl::StartDevicesDiscovery() {
869   connection_handler::ConnectionHandlerImpl::instance()->
870   StartDevicesDiscovery();
871 }
872
873 void ApplicationManagerImpl::SendMessageToMobile(
874   const utils::SharedPtr<smart_objects::SmartObject>& message,
875   bool final_message) {
876   LOG4CXX_INFO(logger_, "ApplicationManagerImpl::SendMessageToMobile");
877
878   if (!message) {
879     LOG4CXX_ERROR(logger_, "Null-pointer message received.");
880     NOTREACHED();
881     return;
882   }
883
884   if (!protocol_handler_) {
885     LOG4CXX_WARN(logger_, "No Protocol Handler set");
886     return;
887   }
888
889   mobile_so_factory().attachSchema(*message);
890   LOG4CXX_INFO(
891     logger_,
892     "Attached schema to message, result if valid: " << message->isValid());
893
894   // Messages to mobile are not yet prioritized so use default priority value
895   utils::SharedPtr<Message> message_to_send(new Message(
896         protocol_handler::MessagePriority::kDefault));
897   if (!ConvertSOtoMessage((*message), (*message_to_send))) {
898     LOG4CXX_WARN(logger_, "Can't send msg to Mobile: failed to create string");
899     return;
900   }
901
902   smart_objects::SmartObject& msg_to_mobile = *message;
903   if (msg_to_mobile[strings::params].keyExists(strings::correlation_id)) {
904     request_ctrl_.terminateRequest(
905       msg_to_mobile[strings::params][strings::correlation_id].asUInt());
906   }
907
908   messages_to_mobile_.PostMessage(impl::MessageToMobile(message_to_send,
909                                   final_message));
910 }
911
912 bool ApplicationManagerImpl::ManageMobileCommand(
913   const utils::SharedPtr<smart_objects::SmartObject>& message) {
914   LOG4CXX_INFO(logger_, "ApplicationManagerImpl::ManageMobileCommand");
915
916   if (!message) {
917     LOG4CXX_WARN(logger_, "Null-pointer message received.");
918     NOTREACHED()
919     return false;
920   }
921
922 #ifdef DEBUG
923   MessageHelper::PrintSmartObject(*message);
924 #endif
925
926   LOG4CXX_INFO(logger_, "Trying to create message in mobile factory.");
927   CommandSharedPtr command = MobileCommandFactory::CreateCommand(message);
928
929   if (!command) {
930     LOG4CXX_WARN(logger_, "Failed to create mobile command from smart object");
931     return false;
932   }
933
934   mobile_apis::FunctionID::eType function_id =
935     static_cast<mobile_apis::FunctionID::eType>(
936       (*message)[strings::params][strings::function_id].asInt());
937
938   // Notifications from HMI have no such parameter
939   uint32_t correlation_id =
940     (*message)[strings::params].keyExists(strings::correlation_id)
941     ? (*message)[strings::params][strings::correlation_id].asUInt()
942     : 0;
943
944   uint32_t connection_key =
945     (*message)[strings::params][strings::connection_key].asUInt();
946
947   uint32_t protocol_type =
948     (*message)[strings::params][strings::protocol_type].asUInt();
949
950   ApplicationSharedPtr app;
951
952   if (((mobile_apis::FunctionID::RegisterAppInterfaceID != function_id) &&
953        (protocol_type == commands::CommandImpl::mobile_protocol_type_)) &&
954       (mobile_apis::FunctionID::UnregisterAppInterfaceID != function_id)) {
955     app = ApplicationManagerImpl::instance()->application(connection_key);
956     if (!app) {
957       LOG4CXX_ERROR_EXT(logger_, "APPLICATION_NOT_REGISTERED");
958       smart_objects::SmartObject* response =
959         MessageHelper::CreateNegativeResponse(
960           connection_key,
961           static_cast<int32_t>(function_id),
962           correlation_id,
963           static_cast<int32_t>(mobile_apis::Result::APPLICATION_NOT_REGISTERED));
964
965       ApplicationManagerImpl::instance()->SendMessageToMobile(response);
966       return false;
967     }
968
969     // Message for "CheckPermission" must be with attached schema
970     mobile_so_factory().attachSchema(*message);
971
972     if (policy_manager_) {
973       LOG4CXX_INFO(
974         logger_,
975         "Checking permissions for  " << app->mobile_app_id()->asString() << " in " << MessageHelper::StringifiedHMILevel(app->hmi_level()) << " rpc " << MessageHelper::StringifiedFunctionID(function_id));
976       policy::CheckPermissionResult result = policy_manager_->CheckPermissions(
977           app->mobile_app_id()->asString(),
978           MessageHelper::StringifiedHMILevel(app->hmi_level()),
979           MessageHelper::StringifiedFunctionID(function_id));
980
981       if (app->hmi_level() == mobile_apis::HMILevel::HMI_NONE
982           && function_id != mobile_apis::FunctionID::UnregisterAppInterfaceID) {
983         app->usage_report().RecordRpcSentInHMINone();
984       }
985
986       if (!result.hmi_level_permitted) {
987         LOG4CXX_WARN(
988           logger_,
989           "Request blocked by policies. " << "FunctionID: " << static_cast<int32_t>(function_id) << " Application HMI status: " << static_cast<int32_t>(app->hmi_level()));
990
991         app->usage_report().RecordPolicyRejectedRpcCall();
992
993         smart_objects::SmartObject* response =
994           MessageHelper::CreateBlockedByPoliciesResponse(function_id,
995               mobile_apis::Result::REJECTED, correlation_id, connection_key);
996
997         ApplicationManagerImpl::instance()->SendMessageToMobile(response);
998         return true;
999       }
1000     }
1001   }
1002
1003   if (command->Init()) {
1004     if ((*message)[strings::params][strings::message_type].asInt() ==
1005         mobile_apis::messageType::request) {
1006       // get application hmi level
1007       mobile_api::HMILevel::eType app_hmi_level =
1008         mobile_api::HMILevel::INVALID_ENUM;
1009       if (app) {
1010         app_hmi_level = app->hmi_level();
1011       }
1012
1013       request_controller::RequestController::TResult result =
1014         request_ctrl_.addRequest(command, app_hmi_level);
1015
1016       if (result == request_controller::RequestController::SUCCESS) {
1017         LOG4CXX_INFO(logger_, "Perform request");
1018       } else if (result ==
1019                  request_controller::RequestController::
1020                  TOO_MANY_PENDING_REQUESTS) {
1021         LOG4CXX_ERROR_EXT(logger_, "Unable to perform request: " <<
1022                           "TOO_MANY_PENDING_REQUESTS");
1023
1024         smart_objects::SmartObject* response =
1025           MessageHelper::CreateNegativeResponse(
1026             connection_key,
1027             static_cast<int32_t>(function_id),
1028             correlation_id,
1029             static_cast<int32_t>(mobile_apis::Result::TOO_MANY_PENDING_REQUESTS));
1030
1031         ApplicationManagerImpl::instance()->SendMessageToMobile(response);
1032         return false;
1033       } else if (result ==
1034                  request_controller::RequestController::TOO_MANY_REQUESTS) {
1035         LOG4CXX_ERROR_EXT(logger_, "Unable to perform request: " <<
1036                           "TOO_MANY_REQUESTS");
1037
1038         MessageHelper::SendOnAppInterfaceUnregisteredNotificationToMobile(
1039           connection_key,
1040           mobile_api::AppInterfaceUnregisteredReason::TOO_MANY_REQUESTS);
1041
1042         UnregisterApplication(connection_key,
1043                               mobile_apis::Result::TOO_MANY_PENDING_REQUESTS,
1044                               true);
1045         return false;
1046       } else if (result ==
1047                  request_controller::RequestController::
1048                  NONE_HMI_LEVEL_MANY_REQUESTS) {
1049         LOG4CXX_ERROR_EXT(logger_, "Unable to perform request: " <<
1050                           "REQUEST_WHILE_IN_NONE_HMI_LEVEL");
1051
1052         MessageHelper::SendOnAppInterfaceUnregisteredNotificationToMobile(
1053           connection_key, mobile_api::AppInterfaceUnregisteredReason::
1054           REQUEST_WHILE_IN_NONE_HMI_LEVEL);
1055
1056         UnregisterApplication(connection_key, mobile_apis::Result::INVALID_ENUM,
1057                               true);
1058         return false;
1059       } else {
1060         LOG4CXX_ERROR_EXT(logger_, "Unable to perform request: Unknown case");
1061         return false;
1062       }
1063     }
1064
1065     command->Run();
1066   }
1067
1068   return true;
1069 }
1070
1071 void ApplicationManagerImpl::SendMessageToHMI(
1072   const utils::SharedPtr<smart_objects::SmartObject>& message) {
1073   LOG4CXX_INFO(logger_, "ApplicationManagerImpl::SendMessageToHMI");
1074
1075   if (!message) {
1076     LOG4CXX_WARN(logger_, "Null-pointer message received.");
1077     NOTREACHED();
1078     return;
1079   }
1080
1081   if (!hmi_handler_) {
1082     LOG4CXX_WARN(logger_, "No HMI Handler set");
1083     return;
1084   }
1085
1086   // SmartObject |message| has no way to declare priority for now
1087   utils::SharedPtr<Message> message_to_send(
1088     new Message(protocol_handler::MessagePriority::kDefault));
1089   if (!message_to_send) {
1090     LOG4CXX_ERROR(logger_, "Null pointer");
1091     return;
1092   }
1093
1094   hmi_so_factory().attachSchema(*message);
1095   LOG4CXX_INFO(
1096     logger_,
1097     "Attached schema to message, result if valid: " << message->isValid());
1098
1099 #ifdef HMI_JSON_API
1100   if (!ConvertSOtoMessage(*message, *message_to_send)) {
1101     LOG4CXX_WARN(logger_,
1102                  "Cannot send message to HMI: failed to create string");
1103     return;
1104   }
1105 #endif  // HMI_JSON_API
1106
1107 #ifdef HMI_DBUS_API
1108   message_to_send->set_smart_object(*message);
1109 #endif  // HMI_DBUS_API
1110
1111   messages_to_hmi_.PostMessage(impl::MessageToHmi(message_to_send));
1112 }
1113
1114 bool ApplicationManagerImpl::ManageHMICommand(
1115   const utils::SharedPtr<smart_objects::SmartObject>& message) {
1116   LOG4CXX_INFO(logger_, "ApplicationManagerImpl::ManageHMICommand");
1117
1118   if (!message) {
1119     LOG4CXX_WARN(logger_, "Null-pointer message received.");
1120     NOTREACHED();
1121     return false;
1122   }
1123
1124 #ifdef DEBUG
1125   MessageHelper::PrintSmartObject(*message);
1126 #endif
1127
1128   CommandSharedPtr command = HMICommandFactory::CreateCommand(message);
1129
1130   if (!command) {
1131     LOG4CXX_WARN(logger_, "Failed to create command from smart object");
1132     return false;
1133   }
1134
1135   if (command->Init()) {
1136     command->Run();
1137     if (command->CleanUp()) {
1138       return true;
1139     }
1140   }
1141   return false;
1142 }
1143
1144 void ApplicationManagerImpl::CreateHMIMatrix(HMIMatrix* matrix) {
1145 }
1146
1147 void ApplicationManagerImpl::CreatePoliciesManager() {
1148   LOG4CXX_INFO(logger_, "CreatePoliciesManager");
1149   policy_manager_ = policy::PolicyHandler::instance()->LoadPolicyLibrary();
1150   if (policy_manager_) {
1151     LOG4CXX_INFO(logger_, "Policy library is loaded, now initing PT");
1152     policy::PolicyHandler::instance()->InitPolicyTable();
1153   }
1154 }
1155
1156 bool ApplicationManagerImpl::CheckPolicies(smart_objects::SmartObject* message,
1157     ApplicationSharedPtr app) {
1158   return true;
1159 }
1160
1161 bool ApplicationManagerImpl::CheckHMIMatrix(
1162   smart_objects::SmartObject* message) {
1163   return true;
1164 }
1165
1166 bool ApplicationManagerImpl::ConvertMessageToSO(
1167   const Message& message, smart_objects::SmartObject& output) {
1168   LOG4CXX_INFO(
1169     logger_,
1170     "\t\t\tMessage to convert: protocol " << message.protocol_version()
1171     << "; json " << message.json_message());
1172
1173   switch (message.protocol_version()) {
1174     case ProtocolVersion::kV2: {
1175
1176       if (!formatters::CFormatterJsonSDLRPCv2::fromString(
1177             message.json_message(),
1178             output,
1179             message.function_id(),
1180             message.type(),
1181             message.correlation_id())
1182           || !mobile_so_factory().attachSchema(output)
1183           || ((output.validate() != smart_objects::Errors::OK)
1184               && (output.validate() !=
1185                   smart_objects::Errors::UNEXPECTED_PARAMETER))) {
1186         LOG4CXX_WARN(logger_, "Failed to parse string to smart object");
1187         utils::SharedPtr<smart_objects::SmartObject> response(
1188           MessageHelper::CreateNegativeResponse(
1189             message.connection_key(), message.function_id(),
1190             message.correlation_id(), mobile_apis::Result::INVALID_DATA));
1191         ManageMobileCommand(response);
1192         return false;
1193       }
1194       LOG4CXX_INFO(
1195         logger_,
1196         "Convertion result for sdl object is true" << " function_id "
1197         << output[jhs::S_PARAMS][jhs::S_FUNCTION_ID].asInt());
1198       output[strings::params][strings::connection_key] =
1199         message.connection_key();
1200       if (message.binary_data()) {
1201         output[strings::params][strings::binary_data] =
1202           *(message.binary_data());
1203       }
1204       break;
1205     }
1206     case ProtocolVersion::kHMI: {
1207       int32_t result = formatters::FormatterJsonRpc::FromString <
1208                        hmi_apis::FunctionID::eType, hmi_apis::messageType::eType > (
1209                          message.json_message(), output);
1210       LOG4CXX_INFO(
1211         logger_,
1212         "Convertion result: " << result << " function id "
1213         << output[jhs::S_PARAMS][jhs::S_FUNCTION_ID].asInt());
1214       if (!hmi_so_factory().attachSchema(output)) {
1215         LOG4CXX_WARN(logger_, "Failed to attach schema to object.");
1216         return false;
1217       }
1218       if (output.validate() != smart_objects::Errors::OK &&
1219           output.validate() != smart_objects::Errors::UNEXPECTED_PARAMETER) {
1220         LOG4CXX_WARN(
1221           logger_,
1222           "Incorrect parameter from HMI");
1223         output.erase(strings::msg_params);
1224         output[strings::params][hmi_response::code] =
1225           hmi_apis::Common_Result::INVALID_DATA;
1226         output[strings::msg_params][strings::info] =
1227           std::string("Received invalid data on HMI response");
1228       }
1229       break;
1230     }
1231     case ProtocolVersion::kV1: {
1232       static NsSmartDeviceLinkRPC::V1::v4_protocol_v1_2_no_extra v1_shema;
1233
1234       if (message.function_id() == 0 || message.type() == kUnknownType) {
1235         LOG4CXX_ERROR(logger_, "Message received: UNSUPPORTED_VERSION");
1236
1237         int32_t conversation_result =
1238           formatters::CFormatterJsonSDLRPCv1::fromString <
1239           NsSmartDeviceLinkRPC::V1::FunctionID::eType,
1240           NsSmartDeviceLinkRPC::V1::messageType::eType > (
1241             message.json_message(), output);
1242
1243         if (formatters::CFormatterJsonSDLRPCv1::kSuccess
1244             == conversation_result) {
1245
1246           smart_objects::SmartObject params = smart_objects::SmartObject(smart_objects::SmartType::SmartType_Map);
1247
1248           output[strings::params][strings::message_type] =
1249             NsSmartDeviceLinkRPC::V1::messageType::response;
1250           output[strings::params][strings::connection_key] = message.connection_key();
1251
1252           output[strings::msg_params] =
1253             smart_objects::SmartObject(smart_objects::SmartType::SmartType_Map);
1254           output[strings::msg_params][strings::success] = false;
1255           output[strings::msg_params][strings::result_code] =
1256             NsSmartDeviceLinkRPC::V1::Result::UNSUPPORTED_VERSION;
1257
1258           smart_objects::SmartObject* msg_to_send = new smart_objects::SmartObject(output);
1259           v1_shema.attachSchema(*msg_to_send);
1260           SendMessageToMobile(msg_to_send);
1261           return false;
1262         }
1263       }
1264
1265       break;
1266     }
1267     default:
1268       // TODO(PV):
1269       //  removed NOTREACHED() because some app can still have vesion 1.
1270       LOG4CXX_WARN(
1271         logger_,
1272         "Application used unsupported protocol :" << message.protocol_version()
1273         << ".");
1274       return false;
1275   }
1276
1277   LOG4CXX_INFO(logger_, "Successfully parsed message into smart object");
1278   return true;
1279 }
1280
1281 bool ApplicationManagerImpl::ConvertSOtoMessage(
1282   const smart_objects::SmartObject& message, Message& output) {
1283   LOG4CXX_INFO(logger_, "Message to convert");
1284
1285   if (smart_objects::SmartType_Null == message.getType()
1286       || smart_objects::SmartType_Invalid == message.getType()) {
1287     LOG4CXX_WARN(logger_, "Invalid smart object received.");
1288     return false;
1289   }
1290
1291   LOG4CXX_INFO(
1292     logger_,
1293     "Message with protocol: "
1294     << message.getElement(jhs::S_PARAMS).getElement(jhs::S_PROTOCOL_TYPE)
1295     .asInt());
1296
1297   std::string output_string;
1298   switch (message.getElement(jhs::S_PARAMS).getElement(jhs::S_PROTOCOL_TYPE)
1299           .asInt()) {
1300     case 0: {
1301       if (message.getElement(jhs::S_PARAMS).getElement(jhs::S_PROTOCOL_VERSION).asInt() == 1) {
1302         if (!formatters::CFormatterJsonSDLRPCv1::toString(message,
1303             output_string)) {
1304           LOG4CXX_WARN(logger_, "Failed to serialize smart object");
1305           return false;
1306         }
1307         output.set_protocol_version(application_manager::kV1);
1308       } else {
1309         if (!formatters::CFormatterJsonSDLRPCv2::toString(message,
1310             output_string)) {
1311           LOG4CXX_WARN(logger_, "Failed to serialize smart object");
1312           return false;
1313         }
1314         output.set_protocol_version(application_manager::kV2);
1315       }
1316
1317       break;
1318     }
1319     case 1: {
1320       if (!formatters::FormatterJsonRpc::ToString(message, output_string)) {
1321         LOG4CXX_WARN(logger_, "Failed to serialize smart object");
1322         return false;
1323       }
1324       output.set_protocol_version(application_manager::kHMI);
1325       break;
1326     }
1327     default:
1328       NOTREACHED();
1329       return false;
1330   }
1331
1332   LOG4CXX_INFO(logger_, "Convertion result: " << output_string);
1333
1334   output.set_connection_key(
1335     message.getElement(jhs::S_PARAMS).getElement(strings::connection_key)
1336     .asInt());
1337
1338   output.set_function_id(
1339     message.getElement(jhs::S_PARAMS).getElement(jhs::S_FUNCTION_ID).asInt());
1340
1341   output.set_correlation_id(
1342     message.getElement(jhs::S_PARAMS).getElement(jhs::S_CORRELATION_ID)
1343     .asInt());
1344   output.set_message_type(
1345     static_cast<MessageType>(message.getElement(jhs::S_PARAMS).getElement(
1346                                jhs::S_MESSAGE_TYPE).asInt()));
1347
1348   // Currently formatter creates JSON = 3 bytes for empty SmartObject.
1349   // workaround for notification. JSON must be empty
1350   if (mobile_apis::FunctionID::OnAudioPassThruID
1351       != message.getElement(jhs::S_PARAMS).getElement(strings::function_id)
1352       .asInt()) {
1353     output.set_json_message(output_string);
1354   }
1355
1356   if (message.getElement(jhs::S_PARAMS).keyExists(strings::binary_data)) {
1357     application_manager::BinaryData* binaryData =
1358       new application_manager::BinaryData(
1359       message.getElement(jhs::S_PARAMS).getElement(strings::binary_data)
1360       .asBinary());
1361
1362     if (NULL == binaryData) {
1363       LOG4CXX_ERROR(logger_, "Null pointer");
1364       return false;
1365     }
1366     output.set_binary_data(binaryData);
1367   }
1368
1369   LOG4CXX_INFO(logger_, "Successfully parsed smart object into message");
1370   return true;
1371 }
1372
1373 utils::SharedPtr<Message> ApplicationManagerImpl::ConvertRawMsgToMessage(
1374   const protocol_handler::RawMessagePtr& message) {
1375   DCHECK(message);
1376   utils::SharedPtr<Message> outgoing_message;
1377
1378   if (message->service_type() != protocol_handler::kRpc
1379       &&
1380       message->service_type() != protocol_handler::kBulk) {
1381     // skip this message, not under handling of ApplicationManager
1382     LOG4CXX_INFO(logger_, "Skipping message; not the under AM handling.");
1383     return outgoing_message;
1384   }
1385
1386   Message* convertion_result = NULL;
1387   if (message->protocol_version() == 1) {
1388     convertion_result =
1389       MobileMessageHandler::HandleIncomingMessageProtocolV1(message);
1390   } else if (message->protocol_version() == 2) {
1391     convertion_result =
1392       MobileMessageHandler::HandleIncomingMessageProtocolV2(message);
1393   } else {
1394     LOG4CXX_WARN(logger_, "Unknown protocol version.");
1395     return outgoing_message;
1396   }
1397
1398   if (convertion_result) {
1399     outgoing_message = convertion_result;
1400   } else {
1401     LOG4CXX_ERROR(logger_, "Received invalid message");
1402   }
1403   return outgoing_message;
1404 }
1405
1406 void ApplicationManagerImpl::ProcessMessageFromMobile(
1407   const utils::SharedPtr<Message>& message) {
1408   LOG4CXX_INFO(logger_, "ApplicationManagerImpl::ProcessMessageFromMobile()");
1409
1410   utils::SharedPtr<smart_objects::SmartObject> so_from_mobile(
1411     new smart_objects::SmartObject);
1412
1413   if (!so_from_mobile) {
1414     LOG4CXX_ERROR(logger_, "Null pointer");
1415     return;
1416   }
1417
1418   if (!ConvertMessageToSO(*message, *so_from_mobile)) {
1419     LOG4CXX_ERROR(logger_, "Cannot create smart object from message");
1420     return;
1421   }
1422
1423   if (!ManageMobileCommand(so_from_mobile)) {
1424     LOG4CXX_ERROR(logger_, "Received command didn't run successfully");
1425   }
1426 }
1427
1428 void ApplicationManagerImpl::ProcessMessageFromHMI(
1429   const utils::SharedPtr<Message>& message) {
1430   LOG4CXX_INFO(logger_, "ApplicationManagerImpl::ProcessMessageFromHMI()");
1431   utils::SharedPtr<smart_objects::SmartObject> smart_object(
1432     new smart_objects::SmartObject);
1433
1434   if (!smart_object) {
1435     LOG4CXX_ERROR(logger_, "Null pointer");
1436     return;
1437   }
1438
1439 #ifdef HMI_JSON_API
1440   if (!ConvertMessageToSO(*message, *smart_object)) {
1441     LOG4CXX_ERROR(logger_, "Cannot create smart object from message");
1442     return;
1443   }
1444 #endif  // HMI_JSON_API
1445
1446 #ifdef HMI_DBUS_API
1447   *smart_object = message->smart_object();
1448 #endif  // HMI_DBUS_API
1449
1450   LOG4CXX_INFO(logger_, "Converted message, trying to create hmi command");
1451   if (!ManageHMICommand(smart_object)) {
1452     LOG4CXX_ERROR(logger_, "Received command didn't run successfully");
1453   }
1454 }
1455
1456 hmi_apis::HMI_API& ApplicationManagerImpl::hmi_so_factory() {
1457   if (!hmi_so_factory_) {
1458     hmi_so_factory_ = new hmi_apis::HMI_API;
1459     if (!hmi_so_factory_) {
1460       LOG4CXX_ERROR(logger_, "Out of memory");
1461       NOTREACHED();
1462     }
1463   }
1464   return *hmi_so_factory_;
1465 }
1466
1467 mobile_apis::MOBILE_API& ApplicationManagerImpl::mobile_so_factory() {
1468   if (!mobile_so_factory_) {
1469     mobile_so_factory_ = new mobile_apis::MOBILE_API;
1470     if (!mobile_so_factory_) {
1471       LOG4CXX_ERROR(logger_, "Out of memory.");
1472       NOTREACHED();
1473     }
1474   }
1475   return *mobile_so_factory_;
1476 }
1477
1478 HMICapabilities& ApplicationManagerImpl::hmi_capabilities() {
1479   return hmi_capabilities_;
1480 }
1481
1482 void ApplicationManagerImpl::addNotification(const CommandSharedPtr& ptr) {
1483   notification_list_.push_back(ptr);
1484 }
1485
1486 void ApplicationManagerImpl::removeNotification(const CommandSharedPtr& ptr) {
1487   std::list<CommandSharedPtr>::iterator it = notification_list_.begin();
1488   for (; notification_list_.end() != it; ++it) {
1489     if (*it == ptr) {
1490       notification_list_.erase(it);
1491       break;
1492     }
1493   }
1494 }
1495
1496 void ApplicationManagerImpl::updateRequestTimeout(uint32_t connection_key,
1497     uint32_t mobile_correlation_id,
1498     uint32_t new_timeout_value) {
1499   request_ctrl_.updateRequestTimeout(connection_key, mobile_correlation_id,
1500                                      new_timeout_value);
1501 }
1502
1503 const uint32_t ApplicationManagerImpl::application_id
1504 (const int32_t correlation_id) {
1505   // ykazakov: there is no erase for const iterator for QNX
1506   std::map<const int32_t, const uint32_t>::iterator it =
1507     appID_list_.find(correlation_id);
1508   if (appID_list_.end() != it) {
1509     const uint32_t app_id = it->second;
1510     appID_list_.erase(it);
1511     return app_id;
1512   } else {
1513     return 0;
1514   }
1515 }
1516
1517 void ApplicationManagerImpl::set_application_id(const int32_t correlation_id,
1518     const uint32_t app_id) {
1519   appID_list_.insert(std::pair<const int32_t, const uint32_t>
1520                      (correlation_id, app_id));
1521 }
1522
1523 void ApplicationManagerImpl::SetUnregisterAllApplicationsReason(
1524   mobile_api::AppInterfaceUnregisteredReason::eType reason) {
1525   unregister_reason_ = reason;
1526 }
1527
1528 void ApplicationManagerImpl::HeadUnitReset(
1529   mobile_api::AppInterfaceUnregisteredReason::eType reason) {
1530   switch (reason) {
1531     case mobile_api::AppInterfaceUnregisteredReason::MASTER_RESET:
1532       policy::PolicyHandler::instance()->InitPolicyTable();
1533       break;
1534     case mobile_api::AppInterfaceUnregisteredReason::FACTORY_DEFAULTS:
1535       policy::PolicyHandler::instance()->RevertPolicyTable();
1536       break;
1537   }
1538 }
1539
1540 void ApplicationManagerImpl::UnregisterAllApplications() {
1541   LOG4CXX_INFO(logger_, "ApplicationManagerImpl::UnregisterAllApplications " <<
1542       unregister_reason_);
1543
1544   hmi_cooperating_ = false;
1545
1546   std::set<ApplicationSharedPtr>::iterator it = application_list_.begin();
1547   while (it != application_list_.end()) {
1548     MessageHelper::SendOnAppInterfaceUnregisteredNotificationToMobile(
1549         (*it)->app_id(), unregister_reason_);
1550
1551     UnregisterApplication((*it)->app_id(), mobile_apis::Result::INVALID_ENUM,
1552                           true);
1553     it = application_list_.begin();
1554   }
1555   resume_controller().IgnitionOff();
1556 }
1557
1558 void ApplicationManagerImpl::UnregisterApplication(
1559     const uint32_t& app_id, mobile_apis::Result::eType reason,
1560     bool is_resuming) {
1561   LOG4CXX_INFO(logger_,
1562       "ApplicationManagerImpl::UnregisterApplication " << app_id);
1563
1564   switch (reason) {
1565     case mobile_apis::Result::DISALLOWED:
1566     case mobile_apis::Result::USER_DISALLOWED:
1567     case mobile_apis::Result::INVALID_CERT:
1568     case mobile_apis::Result::EXPIRED_CERT:
1569     case mobile_apis::Result::TOO_MANY_PENDING_REQUESTS: {
1570       application(app_id)->usage_report().RecordRemovalsForBadBehavior();
1571       break;
1572     }
1573   }
1574
1575   sync_primitives::AutoLock lock(applications_list_lock_);
1576
1577   std::map<int32_t, ApplicationSharedPtr>::iterator it = applications_.find(app_id);
1578   if (applications_.end() == it) {
1579     LOG4CXX_INFO(logger_, "Application is already unregistered.");
1580     return;
1581   }
1582   ApplicationSharedPtr app_to_remove = it->second;
1583   if (is_resuming) {
1584     resume_ctrl_.SaveApplication(app_to_remove);
1585   }
1586   if (audio_pass_thru_active_) {
1587     // May be better to put this code in MessageHelper?
1588     end_audio_pass_thru();
1589     StopAudioPassThru(app_id);
1590     MessageHelper::SendStopAudioPathThru();
1591   }
1592   MessageHelper::RemoveAppDataFromHMI(it->second);
1593   MessageHelper::SendOnAppUnregNotificationToHMI(it->second);
1594   applications_.erase(it);
1595   application_list_.erase(app_to_remove);
1596   request_ctrl_.terminateAppRequests(app_id);
1597
1598   return;
1599 }
1600
1601 void ApplicationManagerImpl::Handle(const impl::MessageFromMobile& message) {
1602   LOG4CXX_INFO(logger_, "Received message from Mobile side");
1603
1604   if (!message) {
1605     LOG4CXX_ERROR(logger_, "Null-pointer message received.");
1606     return;
1607   }
1608   ProcessMessageFromMobile(message);
1609 }
1610
1611 void ApplicationManagerImpl::Handle(const impl::MessageToMobile& message) {
1612   protocol_handler::RawMessage* rawMessage = 0;
1613   if (message->protocol_version() == application_manager::kV1) {
1614     rawMessage = MobileMessageHandler::HandleOutgoingMessageProtocolV1(message);
1615   } else if (message->protocol_version() == application_manager::kV2) {
1616     rawMessage = MobileMessageHandler::HandleOutgoingMessageProtocolV2(message);
1617   } else {
1618     return;
1619   }
1620   if (!rawMessage) {
1621     LOG4CXX_ERROR(logger_, "Failed to create raw message.");
1622     return;
1623   }
1624
1625   if (!protocol_handler_) {
1626     LOG4CXX_WARN(logger_,
1627                  "Protocol Handler is not set; cannot send message to mobile.");
1628     return;
1629   }
1630
1631   protocol_handler_->SendMessageToMobileApp(rawMessage, message.is_final);
1632
1633   LOG4CXX_INFO(logger_, "Message for mobile given away.");
1634 }
1635
1636 void ApplicationManagerImpl::Handle(const impl::MessageFromHmi& message) {
1637   LOG4CXX_INFO(logger_, "Received message from hmi");
1638
1639   if (!message) {
1640     LOG4CXX_ERROR(logger_, "Null-pointer message received.");
1641     return;
1642   }
1643
1644   ProcessMessageFromHMI(message);
1645 }
1646
1647 void ApplicationManagerImpl::Handle(const impl::MessageToHmi& message) {
1648   LOG4CXX_INFO(logger_, "Received message to hmi");
1649   if (!hmi_handler_) {
1650     LOG4CXX_ERROR(logger_, "Observer is not set for HMIMessageHandler");
1651     return;
1652   }
1653
1654   hmi_handler_->SendMessageToHMI(message);
1655   LOG4CXX_INFO(logger_, "Message from hmi given away.");
1656 }
1657
1658
1659 void ApplicationManagerImpl::Mute(VRTTSSessionChanging changing_state) {
1660   mobile_apis::AudioStreamingState::eType state =
1661     hmi_capabilities_.attenuated_supported()
1662     ? mobile_apis::AudioStreamingState::ATTENUATED
1663     : mobile_apis::AudioStreamingState::NOT_AUDIBLE;
1664
1665   std::set<ApplicationSharedPtr>::const_iterator it = application_list_.begin();
1666   std::set<ApplicationSharedPtr>::const_iterator itEnd = application_list_.end();
1667   for (; it != itEnd; ++it) {
1668     if ((*it)->is_media_application()) {
1669       if (kTTSSessionChanging == changing_state) {
1670         (*it)->set_tts_speak_state(true);
1671       }
1672       if ((*it)->audio_streaming_state() != state) {
1673         (*it)->set_audio_streaming_state(state);
1674         MessageHelper::SendHMIStatusNotification(*(*it));
1675       }
1676     }
1677   }
1678 }
1679
1680 void ApplicationManagerImpl::Unmute(VRTTSSessionChanging changing_state) {
1681   std::set<ApplicationSharedPtr>::const_iterator it = application_list_.begin();
1682   std::set<ApplicationSharedPtr>::const_iterator itEnd = application_list_.end();
1683   for (; it != itEnd; ++it) {
1684     if ((*it)->is_media_application()) {
1685       if (kTTSSessionChanging == changing_state) {
1686         (*it)->set_tts_speak_state(false);
1687       }
1688       if ((!(vr_session_started())) &&
1689           ((*it)->audio_streaming_state() !=
1690            mobile_apis::AudioStreamingState::AUDIBLE)) {
1691         (*it)->set_audio_streaming_state(
1692           mobile_apis::AudioStreamingState::AUDIBLE);
1693         MessageHelper::SendHMIStatusNotification(*(*it));
1694       }
1695     }
1696   }
1697 }
1698
1699 mobile_apis::Result::eType ApplicationManagerImpl::SaveBinary(
1700   const std::vector<uint8_t>& binary_data, const std::string& file_path,
1701   const uint32_t offset) {
1702   LOG4CXX_INFO(
1703     logger_,
1704     "SaveBinaryWithOffset  binary_size = " << binary_data.size()
1705     << " offset = " << offset);
1706
1707   if (binary_data.size() > file_system::GetAvailableDiskSpace()) {
1708     LOG4CXX_ERROR(logger_, "Out of free disc space.");
1709     return mobile_apis::Result::OUT_OF_MEMORY;
1710   }
1711
1712   uint32_t file_size = file_system::FileSize(file_path);
1713   std::ofstream* file_stream;
1714   if (offset != 0) {
1715     if (file_size != offset) {
1716       LOG4CXX_INFO(
1717         logger_,
1718         "ApplicationManagerImpl::SaveBinaryWithOffset offset does'n match existing filesize");
1719       return mobile_apis::Result::INVALID_DATA;
1720     }
1721     file_stream = file_system::Open(file_path, std::ios_base::app);
1722   } else {
1723     LOG4CXX_INFO(
1724       logger_,
1725       "ApplicationManagerImpl::SaveBinaryWithOffset offset is 0, rewrite");
1726     // if offset == 0: rewrite file
1727     file_stream = file_system::Open(file_path, std::ios_base::out);
1728   }
1729
1730   if (!file_system::Write(file_stream, binary_data.data(),
1731                           binary_data.size())) {
1732     file_system::Close(file_stream);
1733     return mobile_apis::Result::GENERIC_ERROR;
1734   }
1735   file_system::Close(file_stream);
1736   LOG4CXX_INFO(logger_, "Successfully write data to file");
1737   return mobile_apis::Result::SUCCESS;
1738 }
1739
1740 bool ApplicationManagerImpl::IsHMICooperating() const {
1741   return hmi_cooperating_;
1742 }
1743
1744 }  // namespace application_manager