365c3b8089a24ddf01a855e2fa33ab34366f207d
[platform/core/uifw/multi-assistant-service.git] / src / service_ipc_dbus.cpp
1 /*
2  * Copyright 2020 Samsung Electronics Co., Ltd
3  *
4  * Licensed under the Flora License, Version 1.1 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://floralicense.org/license/
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17
18 #include <dirent.h>
19 #include <dlfcn.h>
20 #include <message_port.h>
21
22 #include <chrono>
23 #include <atomic>
24
25 #include "service_common.h"
26 #include "service_main.h"
27 #include "service_ipc_dbus.h"
28
29 #ifdef PRINT_DETAILED_TIMEINFO
30 static long long int get_time_interval_count(
31         std::chrono::time_point<std::chrono::steady_clock> time_point_1,
32         std::chrono::time_point<std::chrono::steady_clock> time_point_2) {
33         auto interval = time_point_2 - time_point_1;
34         return static_cast<long long int>(
35                 std::chrono::duration_cast<std::chrono::milliseconds>(interval).count());
36 }
37 #endif
38
39 std::atomic_size_t gAudioDataMileage{0};
40
41 static void message_port_cb(int local_port_id,
42         const char *remote_app_id, const char *remote_port,
43         bool trusted_remote_port, bundle *message, void *user_data)
44 {
45         CServiceIpcDbus *service_ipc = static_cast<CServiceIpcDbus *>(user_data);
46         if (!service_ipc) {
47                 MAS_LOGE("Invalid user_data");
48                 return;
49         }
50
51         CServiceIpcDbusDispatcher* dispatcher = service_ipc->get_dispatcher();
52         if (!dispatcher) {
53                 MAS_LOGE("Dispatcher not found");
54                 return;
55         }
56
57         IServiceIpcObserver *observer = dispatcher->get_ipc_observer();
58         if (!observer) {
59                 MAS_LOGE("Observer not found");
60                 return;
61         }
62
63         char *command = nullptr;
64         bundle_get_str(message, "command", &command);
65         if (command) {
66                 const char *szStartStreamingCommand = "start_streaming_current_utterance";
67                 if (strncmp(command, szStartStreamingCommand, strlen(szStartStreamingCommand)) == 0) {
68                         MAS_LOGE("AP sent start streaming request");
69                         observer->on_ap_start_streaming_audio_data(std::string{remote_app_id},
70                                 MA_AUDIO_STREAMING_DATA_TYPE_CURRENT_UTTERANCE);
71                 }
72         }
73 }
74
75 int CServiceIpcDbus::reconnect()
76 {
77         if (!mConnectionSender || !mConnectionListener) {
78                 close_connection();
79
80                 if (0 != open_connection()) {
81                         MAS_LOGE("[ERROR] Fail to reconnect");
82                         return -1;
83                 }
84
85                 MAS_LOGD("[DBUS] Reconnect");
86                 return 0;
87         }
88
89         bool sender_connected = dbus_connection_get_is_connected(mConnectionSender);
90         bool listener_connected = dbus_connection_get_is_connected(mConnectionListener);
91         MAS_LOGW("[DBUS] Sender(%s) Listener(%s)",
92                 sender_connected ? "Connected" : "Not connected", listener_connected ? "Connected" : "Not connected");
93
94         if (false == sender_connected || false == listener_connected) {
95                 close_connection();
96
97                 if (0 != open_connection()) {
98                         MAS_LOGE("[ERROR] Fail to reconnect");
99                         return -1;
100                 }
101
102                 MAS_LOGD("[DBUS] Reconnect");
103         }
104
105         return 0;
106 }
107
108 int CServiceIpcDbus::__dbus_check()
109 {
110         if (NULL == mConnectionSender || NULL == mConnectionListener) {
111                 MAS_LOGE("[ERROR] NULL connection");
112                 return reconnect();
113         }
114         return 0;
115 }
116
117 int CServiceIpcDbus::mas_check_dbus_connection()
118 {
119         if (NULL == mConnectionSender || NULL == mConnectionListener) {
120                 MAS_LOGE("[ERROR] NULL connection sender(%p), listener(%p)", mConnectionSender, mConnectionListener);
121                 return -1;
122         }
123         return 0;
124 }
125
126 int CServiceIpcDbus::send_hello(pid_t pid)
127 {
128         if (0 != __dbus_check()) {
129                 return -1; //MAS_ERROR_OPERATION_FAILED;
130         }
131
132         DBusMessage* msg;
133         DBusError err;
134         dbus_error_init(&err);
135
136         msg = dbus_message_new_method_call(
137                         MA_CLIENT_SERVICE_NAME,
138                         MA_CLIENT_SERVICE_OBJECT_PATH,
139                         MA_CLIENT_SERVICE_INTERFACE,
140                         MAS_METHOD_HELLO);
141
142         if (NULL == msg) {
143                 MAS_LOGE("[DBus ERROR] Request masc hello : Fail to make message");
144                 return -1;
145         }
146
147         int result = -1;
148         DBusMessage* result_msg = NULL;
149         result_msg = dbus_connection_send_with_reply_and_block(mConnectionSender, msg, 500, &err);
150
151         if (dbus_error_is_set(&err)) {
152                 MAS_LOGE("[Dbus ERROR] Dbus Error (%s)", err.message);
153                 dbus_error_free(&err);
154         }
155
156         dbus_message_unref(msg);
157
158         if (NULL != result_msg) {
159                 dbus_message_unref(result_msg);
160                 result = 0;
161         } else {
162                 result = -1; //MAS_ERROR_TIMED_OUT;
163         }
164
165         return result;
166 }
167
168 int CServiceIpcDbus::send_error_message(int reason, const char* err_msg)
169 {
170         if (0 != __dbus_check()) {
171                 return -1; //MAS_ERROR_OPERATION_FAILED;
172         }
173
174         if (NULL == mConnectionSender) {
175                 MAS_LOGE("[Dbus ERROR] Dbus connection is not available");
176                 return -1;
177         }
178
179         DBusMessage* msg = NULL;
180
181         /* create a message */
182         msg = dbus_message_new_signal(
183                 MA_CLIENT_SERVICE_OBJECT_PATH,  /* object name of the signal */
184                 MA_CLIENT_SERVICE_INTERFACE,    /* interface name of the signal */
185                 MAS_METHOD_ERROR);              /* name of the signal */
186
187         if (NULL == msg) {
188                 MAS_LOGE("[Dbus ERROR] Fail to create error message");
189                 return -1;
190         }
191
192         char* temp_err_msg = NULL;
193
194         if (err_msg)
195                 temp_err_msg = strdup(err_msg);
196         else
197                 temp_err_msg = strdup("#NULL");
198
199         dbus_message_append_args(msg,
200                 DBUS_TYPE_INT32, &reason,
201                 DBUS_TYPE_STRING, &temp_err_msg,
202                 DBUS_TYPE_INVALID);
203
204         dbus_message_set_no_reply(msg, TRUE);
205
206         if (!dbus_connection_send(mConnectionSender, msg, NULL)) {
207                 MAS_LOGE("[Dbus ERROR] <<<< error message : Out Of Memory !");
208         } else {
209                 MAS_LOGI("<<<< Send error message : reason(%d), err_msg(%s)", reason, temp_err_msg);
210                 dbus_connection_flush(mConnectionSender);
211         }
212
213         dbus_message_unref(msg);
214
215         if (temp_err_msg)
216                 free(temp_err_msg);
217         return 0;
218 }
219
220 const char *message_port = "ma_streaming_port";
221
222 #define STREAMING_BUFFER_SIZE 4096
223
224 typedef enum {
225         streaming_data_type_audio_data,
226         streaming_data_type_streaming_section
227 } streaming_data_type_e;
228
229 typedef struct {
230         unsigned int streaming_data_size;
231         int streaming_data_type;
232         int streaming_data_serial;
233 } streaming_data_header;
234
235 typedef struct {
236         int event;
237         unsigned int data_size;
238 } streaming_data_audio_data_header;
239
240 typedef struct {
241         int section;
242 } streaming_data_streaming_section_header;
243
244 static void masc_message_port_error(int error)
245 {
246         MAS_LOGE("message_port error found : %s",
247                 (MESSAGE_PORT_ERROR_NONE == error) ? "MESSAGE_PORT_ERROR_NONE" :
248                 (MESSAGE_PORT_ERROR_IO_ERROR == error) ? "MESSAGE_PORT_ERROR_IO_ERROR" :
249                 (MESSAGE_PORT_ERROR_OUT_OF_MEMORY == error) ? "MESSAGE_PORT_ERROR_OUT_OF_MEMORY" :
250                 (MESSAGE_PORT_ERROR_INVALID_PARAMETER == error) ? "MESSAGE_PORT_ERROR_INVALID_PARAMETER" :
251                 (MESSAGE_PORT_ERROR_PORT_NOT_FOUND == error) ? "MESSAGE_PORT_ERROR_PORT_NOT_FOUND" :
252                 (MESSAGE_PORT_ERROR_CERTIFICATE_NOT_MATCH == error) ? "MESSAGE_PORT_ERROR_CERTIFICATE_NOT_MATCH" :
253                 (MESSAGE_PORT_ERROR_MAX_EXCEEDED == error) ? "MESSAGE_PORT_ERROR_MAX_EXCEEDED" :
254                 (MESSAGE_PORT_ERROR_RESOURCE_UNAVAILABLE == error) ? "MESSAGE_PORT_ERROR_RESOURCE_UNAVAILABLE" :
255                 "MESSAGE_PORT_ERROR_UNKNOWN");
256 }
257
258 static long long get_current_milliseconds_after_epoch()
259 {
260         auto now = std::chrono::steady_clock::now();
261         auto now_ms = std::chrono::time_point_cast<std::chrono::milliseconds>(now);
262         /* number of milliseconds since the epoch of system_clock */
263         auto value = now_ms.time_since_epoch();
264
265         return value.count();
266 }
267
268 int CServiceIpcDbus::send_streaming_audio_data(std::string appid, int event, void* data, unsigned int data_size)
269 {
270         if (nullptr == mClientManager) {
271                 MAS_LOGE("mClientManager variable is NULL");
272                 return -1;
273         }
274
275 #ifdef PRINT_DETAILED_TIMEINFO
276         bool flushed = false;
277         auto started = std::chrono::steady_clock::now();
278 #endif
279
280         static unsigned char pending_buffer[STREAMING_BUFFER_SIZE];
281         static size_t pending_buffer_size = 0;
282
283         streaming_data_header header;
284         header.streaming_data_type = 0;
285         header.streaming_data_size = sizeof(streaming_data_header) + sizeof(streaming_data_audio_data_header) + data_size;
286         header.streaming_data_serial = mStreamingDataSerial++;
287
288         streaming_data_audio_data_header audio_data_header;
289         audio_data_header.event = event;
290         audio_data_header.data_size = data_size;
291
292         unsigned char buffer[STREAMING_BUFFER_SIZE];
293         size_t total_size = 0;
294         size_t new_size = 0;
295
296 #ifdef PRINT_DETAILED_TIMEINFO
297         auto checkpoint_1 = std::chrono::steady_clock::now();
298 #endif
299
300         new_size = sizeof(header);
301         if (new_size + total_size <= STREAMING_BUFFER_SIZE) {
302                 memcpy(buffer, &header, new_size);
303                 total_size += new_size;
304         } else {
305                 MAS_LOGE("Buffer overflow : %zu %zu", new_size, total_size);
306                 return -1;
307         }
308
309         new_size = sizeof(audio_data_header);
310         if (new_size + total_size <= STREAMING_BUFFER_SIZE) {
311                 memcpy(buffer + total_size, &audio_data_header, new_size);
312                 total_size += new_size;
313         } else {
314                 MAS_LOGE("Buffer overflow : %zu %zu", new_size, total_size);
315                 return -1;
316         }
317
318         new_size = data_size;
319         if (new_size + total_size <= STREAMING_BUFFER_SIZE) {
320                 memcpy(buffer + total_size, data, new_size);
321                 total_size += new_size;
322         } else {
323                 MAS_LOGE("Buffer overflow : %zu %zu", new_size, total_size);
324                 return -1;
325         }
326         gAudioDataMileage.fetch_add(data_size);
327
328         const long long minimum_flush_interval = 20;
329         static long long last_flush_time = get_current_milliseconds_after_epoch();
330         long long current_time = get_current_milliseconds_after_epoch();
331
332         static int last_serial_waiting_for_flush = -1;
333         if (0 == header.streaming_data_serial % 50 || MAS_SPEECH_STREAMING_EVENT_CONTINUE != event) {
334                 last_serial_waiting_for_flush = header.streaming_data_serial;
335                 MAS_LOGE("queueing streaming data, serial : %d %d %zu",
336                         last_serial_waiting_for_flush, event, gAudioDataMileage.load());
337         }
338
339 #ifdef PRINT_DETAILED_TIMEINFO
340         auto checkpoint_2 = std::chrono::steady_clock::now();
341         auto checkpoint_2_1 = checkpoint_2;
342         auto checkpoint_2_2 = checkpoint_2;
343 #endif
344
345         if (pending_buffer_size + total_size > STREAMING_BUFFER_SIZE ||
346                 MAS_SPEECH_STREAMING_EVENT_FINISH == event ||
347                 current_time - last_flush_time > minimum_flush_interval) {
348
349 #ifdef PRINT_DETAILED_TIMEINFO
350                 flushed = true;
351 #endif
352
353                 last_flush_time = current_time;
354                 bundle *b = bundle_create();
355                 if (b) {
356                         bundle_add_byte(b, "content", pending_buffer, pending_buffer_size);
357 #ifdef PRINT_DETAILED_TIMEINFO
358                         checkpoint_2_1 = std::chrono::steady_clock::now();
359 #endif
360 #if USE_TRUSTED_MESSAGE_PORT
361                         int ret = message_port_send_trusted_message(appid.c_str(), message_port, b);
362 #else
363                         int ret = message_port_send_message(appid.c_str(), message_port, b);
364 #endif
365 #ifdef PRINT_DETAILED_TIMEINFO
366                         checkpoint_2_2 = std::chrono::steady_clock::now();
367 #endif
368                         if (MESSAGE_PORT_ERROR_NONE != ret)
369                                 masc_message_port_error(ret);
370
371                         pending_buffer_size = 0;
372                         bundle_free(b);
373                 } else {
374                         MAS_LOGE("Bundle creation failed!!!");
375                 }
376
377                 if (-1 != last_serial_waiting_for_flush) {
378                         MAS_LOGE("flushing streaming data, serial : %d %zu",
379                                 last_serial_waiting_for_flush, gAudioDataMileage.load());
380                         last_serial_waiting_for_flush =  -1;
381                 }
382         }
383
384 #ifdef PRINT_DETAILED_TIMEINFO
385         auto checkpoint_3 = std::chrono::steady_clock::now();
386 #endif
387         if (MAS_SPEECH_STREAMING_EVENT_FINISH == event) {
388                 MAS_LOGE("Sending FINISH event : %zu", gAudioDataMileage.load());
389                 bundle *b = bundle_create();
390                 if (b) {
391                         bundle_add_byte(b, "content", buffer, total_size);
392 #if USE_TRUSTED_MESSAGE_PORT
393                         int ret = message_port_send_trusted_message(appid.c_str(), message_port, b);
394 #else
395                         int ret = message_port_send_message(appid.c_str(), message_port, b);
396 #endif
397                         if (MESSAGE_PORT_ERROR_NONE != ret)
398                                 masc_message_port_error(ret);
399
400                         bundle_free(b);
401                 } else {
402                         MAS_LOGE("Bundle creation failed!!!");
403                 }
404         } else {
405                 if (pending_buffer_size + total_size <= STREAMING_BUFFER_SIZE) {
406                         memcpy(pending_buffer + pending_buffer_size, buffer, total_size);
407                         pending_buffer_size += total_size;
408                 } else {
409                         MAS_LOGE("Buffer overflow : %zu %zu", pending_buffer_size, total_size);
410                 }
411         }
412
413 #ifdef PRINT_DETAILED_TIMEINFO
414         auto finished = std::chrono::steady_clock::now();
415         long long int count = get_time_interval_count(started, finished);
416
417         if (count > 30) {
418                 long long int count1 = get_time_interval_count(started, checkpoint_1);
419                 long long int count2 = get_time_interval_count(checkpoint_1, checkpoint_2);
420                 long long int count3 = get_time_interval_count(checkpoint_2, checkpoint_3);
421                 long long int count4 = get_time_interval_count(checkpoint_3, finished);
422
423                 long long int count2_1 = get_time_interval_count(checkpoint_2, checkpoint_2_1);
424                 long long int count2_2 = get_time_interval_count(checkpoint_2_1, checkpoint_2_2);
425                 long long int count2_3 = get_time_interval_count(checkpoint_2_2, checkpoint_3);
426
427                 MAS_LOGE("Spent %lld for sending a single message %d [%lld %lld %lld %lld] (%lld %lld %lld)",
428                                 count, flushed, count1, count2, count3, count4, count2_1, count2_2, count2_3);
429         }
430 #endif
431
432         return 0;
433 }
434
435 int CServiceIpcDbus::change_active_state(pid_t pid, int state, const char* wakeup_word,
436         const unsigned char* wakeup_extra_data, size_t wakeup_extra_data_length,
437         const char* wakeup_extra_data_desc)
438 {
439         if (0 != __dbus_check()) {
440                 return -1; //MAS_ERROR_OPERATION_FAILED;
441         }
442
443         DBusMessage* msg;
444
445         DBusError err;
446         dbus_error_init(&err);
447
448         char service_name[64];
449         memset(service_name, '\0', 64);
450         snprintf(service_name, 64, "%s_%d", MA_CLIENT_SERVICE_NAME, pid);
451
452         msg = dbus_message_new_method_call(
453                         service_name,
454                         MA_CLIENT_SERVICE_OBJECT_PATH,
455                         MA_CLIENT_SERVICE_INTERFACE,
456                         MAS_METHOD_ACTIVE_STATE_CHANGE);
457
458         if (NULL == msg) {
459                 MAS_LOGE(">>>> Request mas send activate message : Fail to make message");
460                 return -1; // MAS_ERROR_OPERATION_FAILED;
461         } else {
462                 MAS_LOGD(">>>> Request mas send activate message : %s", service_name);
463         }
464
465         char* temp_wakeup_word = NULL;
466         if (!wakeup_word)
467                 temp_wakeup_word = strdup("#NULL");
468         else
469                 temp_wakeup_word = strdup(wakeup_word);
470
471         char* temp_wakeup_extra_data_desc = NULL;
472         if (!wakeup_extra_data_desc)
473                 temp_wakeup_extra_data_desc = strdup("#NULL");
474         else
475                 temp_wakeup_extra_data_desc = strdup(wakeup_extra_data_desc);
476
477         if (TRUE != dbus_message_append_args(msg,
478                 DBUS_TYPE_INT32, &state,
479                 DBUS_TYPE_STRING, &temp_wakeup_word,
480                 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
481                 &wakeup_extra_data, wakeup_extra_data_length,
482                 DBUS_TYPE_STRING, &temp_wakeup_extra_data_desc,
483                 DBUS_TYPE_INVALID)) {
484                 dbus_message_unref(msg);
485                 MAS_LOGE("[ERROR] Fail to append args");
486                 free(temp_wakeup_word);
487                 free(temp_wakeup_extra_data_desc);
488                 return -1;
489         }
490
491         dbus_message_set_no_reply(msg, TRUE);
492
493         if (1 != dbus_connection_send(mConnectionSender, msg, NULL)) {
494                 MAS_LOGE("[Dbus ERROR] Fail to Send");
495                 free(temp_wakeup_word);
496                 free(temp_wakeup_extra_data_desc);
497                 return -1; // MAS_ERROR_OPERATION_FAILED;
498         } else {
499                 MAS_LOGI("[Dbus DEBUG] Success to Send activate message : %d %d", pid, state);
500                 dbus_connection_flush(mConnectionSender);
501         }
502
503         dbus_message_unref(msg);
504
505         if (temp_wakeup_word)
506                 free(temp_wakeup_word);
507
508         if (temp_wakeup_extra_data_desc)
509                 free(temp_wakeup_extra_data_desc);
510
511         return 0;
512 }
513
514 int CServiceIpcDbus::send_preprocessing_information(pid_t pid, const char* app_id)
515 {
516         if (0 != __dbus_check()) {
517                 return -1; //MAS_ERROR_OPERATION_FAILED;
518         }
519
520         DBusMessage* msg;
521
522         DBusError err;
523         dbus_error_init(&err);
524
525         char service_name[64];
526         memset(service_name, '\0', 64);
527         snprintf(service_name, 64, "%s_%d", MA_CLIENT_SERVICE_NAME, pid);
528
529         msg = dbus_message_new_method_call(
530                         service_name,
531                         MA_CLIENT_SERVICE_OBJECT_PATH,
532                         MA_CLIENT_SERVICE_INTERFACE,
533                         MAS_METHOD_SEND_PREPROCESSING_INFORMATION);
534
535         if (NULL == msg) {
536                 MAS_LOGE(">>>> Request mas send preprocessing assistant information : Fail to make message");
537                 return -1; // MAS_ERROR_OPERATION_FAILED;
538         } else {
539                 MAS_LOGD(">>>> Request mas send preprocessing assistant information : %s", service_name);
540         }
541
542         char* temp_app_id = NULL;
543         if (!app_id)
544                 temp_app_id = strdup("#NULL");
545         else
546                 temp_app_id = strdup(app_id);
547
548         if (TRUE != dbus_message_append_args(msg,
549                 DBUS_TYPE_STRING, &temp_app_id,
550                 DBUS_TYPE_INVALID)) {
551                 dbus_message_unref(msg);
552                 MAS_LOGE("[ERROR] Fail to append args");
553                 if (temp_app_id)
554                         free(temp_app_id);
555                 return -1;
556         }
557
558         dbus_message_set_no_reply(msg, TRUE);
559
560         if (1 != dbus_connection_send(mConnectionSender, msg, NULL)) {
561                 MAS_LOGE("[Dbus ERROR] Fail to Send");
562                 if (temp_app_id)
563                         free(temp_app_id);
564                 return -1; // MAS_ERROR_OPERATION_FAILED;
565         } else {
566                 MAS_LOGI("[Dbus DEBUG] Success to Send preprocessing assistant information : %d %s", pid, app_id);
567                 dbus_connection_flush(mConnectionSender);
568         }
569
570         dbus_message_unref(msg);
571
572         if (temp_app_id)
573                 free(temp_app_id);
574
575         return 0;
576 }
577
578 int CServiceIpcDbus::send_streaming_section_changed(pid_t pid, int section)
579 {
580         if (nullptr == mClientManager) {
581                 MAS_LOGE("mClientManager variable is NULL");
582                 return -1;
583         }
584
585         bundle *b = bundle_create();
586
587         streaming_data_header header;
588         header.streaming_data_type = 1;
589         header.streaming_data_size = sizeof(streaming_data_header) + sizeof(streaming_data_streaming_section_header);
590         header.streaming_data_serial = mStreamingDataSerial++;
591
592         streaming_data_streaming_section_header streaming_section_header;
593         streaming_section_header.section = section;
594
595         unsigned char buffer[STREAMING_BUFFER_SIZE];
596         size_t total_size = 0;
597         memcpy(buffer, &header, sizeof(header));
598         total_size += sizeof(header);
599         memcpy(buffer + total_size, &streaming_section_header, sizeof(streaming_section_header));
600         total_size += sizeof(streaming_section_header);
601
602         bundle_add_byte(b, "content", buffer, total_size);
603 #if USE_TRUSTED_MESSAGE_PORT
604         int ret = message_port_send_trusted_message(
605                 mClientManager->find_client_appid_by_pid(pid).c_str(), message_port, b);
606 #else
607         int ret = message_port_send_message(
608                 mClientManager->find_client_appid_by_pid(pid).c_str(), message_port, b);
609 #endif
610         if (MESSAGE_PORT_ERROR_NONE != ret)
611                 masc_message_port_error(ret);
612
613         bundle_free(b);
614
615         return 0;
616 }
617
618 int CServiceIpcDbus::send_preprocessing_result(pid_t pid, bool result)
619 {
620         if (0 != __dbus_check()) {
621                 return -1; //MAS_ERROR_OPERATION_FAILED;
622         }
623
624         DBusMessage* msg;
625
626         DBusError err;
627         dbus_error_init(&err);
628
629         char service_name[64];
630         memset(service_name, '\0', 64);
631         snprintf(service_name, 64, "%s_%d", MA_CLIENT_SERVICE_NAME, pid);
632
633         msg = dbus_message_new_method_call(
634                         service_name,
635                         MA_CLIENT_SERVICE_OBJECT_PATH,
636                         MA_CLIENT_SERVICE_INTERFACE,
637                         MAS_METHOD_SEND_PREPROCESSING_RESULT);
638
639         if (NULL == msg) {
640                 MAS_LOGE(">>>> Request mas send preprocessing result : Fail to make message");
641                 return -1; // MAS_ERROR_OPERATION_FAILED;
642         } else {
643                 MAS_LOGD(">>>> Request mas send preprocessing result : %s", service_name);
644         }
645
646         int temp_result = result;
647
648         if (TRUE != dbus_message_append_args(msg,
649                 DBUS_TYPE_INT32, &temp_result,
650                 DBUS_TYPE_INVALID)) {
651                 dbus_message_unref(msg);
652                 MAS_LOGE("[ERROR] Fail to append args");
653                 return -1;
654         }
655
656         dbus_message_set_no_reply(msg, TRUE);
657
658         if (1 != dbus_connection_send(mConnectionSender, msg, NULL)) {
659                 MAS_LOGE("[Dbus ERROR] Fail to Send");
660                 return -1; // MAS_ERROR_OPERATION_FAILED;
661         } else {
662                 MAS_LOGI("[Dbus DEBUG] Success to Send preprocessing result : %d %d", pid, temp_result);
663                 dbus_connection_flush(mConnectionSender);
664         }
665
666         dbus_message_unref(msg);
667
668         return 0;
669 }
670
671 int CServiceIpcDbus::send_wakeup_engine_command(pid_t pid, const char* command)
672 {
673         if (0 != __dbus_check()) {
674                 return -1; //MAS_ERROR_OPERATION_FAILED;
675         }
676
677         DBusMessage* msg;
678
679         DBusError err;
680         dbus_error_init(&err);
681
682         char service_name[64];
683         memset(service_name, '\0', 64);
684         snprintf(service_name, 64, "%s_%d", MA_CLIENT_SERVICE_NAME, pid);
685
686         msg = dbus_message_new_method_call(
687                         service_name,
688                         MA_CLIENT_SERVICE_OBJECT_PATH,
689                         MA_CLIENT_SERVICE_INTERFACE,
690                         MAS_METHOD_SEND_WAKEUP_ENGINE_COMMAND);
691
692         if (NULL == msg) {
693                 MAS_LOGE(">>>> Request mas send wakeup engine command : Fail to make message");
694                 return -1; // MAS_ERROR_OPERATION_FAILED;
695         } else {
696                 MAS_LOGD(">>>> Request mas send wakeup engine command : %s", service_name);
697         }
698
699         char* temp_command = NULL;
700         if (!command)
701                 temp_command = strdup("#NULL");
702         else
703                 temp_command = strdup(command);
704
705         if (TRUE != dbus_message_append_args(msg,
706                 DBUS_TYPE_STRING, &temp_command,
707                 DBUS_TYPE_INVALID)) {
708                 dbus_message_unref(msg);
709                 MAS_LOGE("[ERROR] Fail to append args");
710                 if (temp_command)
711                         free(temp_command);
712                 return -1;
713         }
714
715         dbus_message_set_no_reply(msg, TRUE);
716
717         if (1 != dbus_connection_send(mConnectionSender, msg, NULL)) {
718                 MAS_LOGE("[Dbus ERROR] Fail to Send");
719                 if (temp_command)
720                         free(temp_command);
721                 return -1; // MAS_ERROR_OPERATION_FAILED;
722         } else {
723                 MAS_LOGI("[Dbus DEBUG] Success to Send wakeup_engine_command : %d %s", pid, command);
724                 dbus_connection_flush(mConnectionSender);
725         }
726
727         dbus_message_unref(msg);
728
729         if (temp_command)
730                 free(temp_command);
731
732         return 0;
733 }
734
735 int CServiceIpcDbus::change_service_state(pid_t pid, int state)
736 {
737         if (0 != __dbus_check()) {
738                 return -1; //MAS_ERROR_OPERATION_FAILED;
739         }
740
741         DBusMessage* msg;
742
743         DBusError err;
744         dbus_error_init(&err);
745
746         char service_name[64];
747         memset(service_name, '\0', 64);
748         snprintf(service_name, 64, "%s_%d", MA_CLIENT_SERVICE_NAME, pid);
749
750         msg = dbus_message_new_method_call(
751                         service_name,
752                         MA_CLIENT_SERVICE_OBJECT_PATH,
753                         MA_CLIENT_SERVICE_INTERFACE,
754                         MAS_METHOD_SERVICE_STATE_CHANGE);
755
756         if (NULL == msg) {
757                 MAS_LOGE(">>>> Request mas send service state message : Fail to make message");
758                 return -1; // MAS_ERROR_OPERATION_FAILED;
759         } else {
760                 MAS_LOGD(">>>> Request mas send service state message : %s", service_name);
761         }
762
763         if (TRUE != dbus_message_append_args(msg,
764                 DBUS_TYPE_INT32, &state,
765                 DBUS_TYPE_INVALID)) {
766                 dbus_message_unref(msg);
767                 MAS_LOGE("[ERROR] Fail to append args");
768                 return -1;
769         }
770
771         dbus_message_set_no_reply(msg, TRUE);
772
773         if (1 != dbus_connection_send(mConnectionSender, msg, NULL)) {
774                 MAS_LOGE("[Dbus ERROR] Fail to Send");
775                 return -1; // MAS_ERROR_OPERATION_FAILED;
776         } else {
777                 MAS_LOGI("[Dbus DEBUG] Success to Send service state message : %d %d", pid, state);
778                 dbus_connection_flush(mConnectionSender);
779         }
780
781         dbus_message_unref(msg);
782         return 0;
783 }
784
785 int CServiceIpcDbus::change_voice_key_status(pid_t pid, int status)
786 {
787         if (0 != __dbus_check()) {
788                 return -1; //MAS_ERROR_OPERATION_FAILED;
789         }
790
791         DBusMessage* msg;
792
793         DBusError err;
794         dbus_error_init(&err);
795
796         char service_name[64];
797         memset(service_name, '\0', 64);
798         snprintf(service_name, 64, "%s_%d", MA_CLIENT_SERVICE_NAME, pid);
799
800         msg = dbus_message_new_method_call(
801                         service_name,
802                         MA_CLIENT_SERVICE_OBJECT_PATH,
803                         MA_CLIENT_SERVICE_INTERFACE,
804                         MAS_METHOD_VOICE_KEY_STATUS_CHANGE);
805
806         if (NULL == msg) {
807                 MAS_LOGE(">>>> Request mas send voice key status change message : Fail to make message");
808                 return -1; // MAS_ERROR_OPERATION_FAILED;
809         } else {
810                 MAS_LOGD(">>>> Request mas send voice key status change message : %s", service_name);
811         }
812
813         if (TRUE != dbus_message_append_args(msg,
814                 DBUS_TYPE_INT32, &status,
815                 DBUS_TYPE_INVALID)) {
816                 dbus_message_unref(msg);
817                 MAS_LOGE("[ERROR] Fail to append args");
818                 return -1;
819         }
820
821         dbus_message_set_no_reply(msg, TRUE);
822
823         if (1 != dbus_connection_send(mConnectionSender, msg, NULL)) {
824                 MAS_LOGE("[Dbus ERROR] Fail to Send");
825                 return -1; // MAS_ERROR_OPERATION_FAILED;
826         } else {
827                 MAS_LOGI("[Dbus DEBUG] Success to Send voice key status change : %d %d", pid, status);
828                 dbus_connection_flush(mConnectionSender);
829         }
830
831         dbus_message_unref(msg);
832         return 0;
833 }
834
835 int CServiceIpcDbus::masc_ui_dbus_send_hello(void)
836 {
837         if (0 != __dbus_check()) {
838                 return -1; //MAS_ERROR_OPERATION_FAILED;
839         }
840
841         DBusMessage* msg;
842
843         DBusError err;
844         dbus_error_init(&err);
845
846         msg = dbus_message_new_method_call(
847                         MA_UI_CLIENT_SERVICE_NAME,
848                         MA_UI_CLIENT_SERVICE_OBJECT_PATH,
849                         MA_UI_CLIENT_SERVICE_INTERFACE,
850                         MAS_METHOD_HELLO);
851
852         if (NULL == msg) {
853                 MAS_LOGE("[DBus ERROR] Request masc hello : Fail to make message");
854                 return -1;
855         }
856
857         DBusMessage* result_msg = NULL;
858         int result = 0;
859
860         result_msg = dbus_connection_send_with_reply_and_block(mConnectionSender, msg, 500, &err);
861
862         if (dbus_error_is_set(&err)) {
863                 MAS_LOGE("[Dbus ERROR] Dbus Error (%s)", err.message);
864                 dbus_error_free(&err);
865         }
866
867         dbus_message_unref(msg);
868
869         if (NULL != result_msg) {
870                 dbus_message_unref(result_msg);
871                 result = 0;
872         } else {
873                 result = -1; //ERROR_TIMED_OUT;
874         }
875
876         return result;
877 }
878
879 int CServiceIpcDbus::masc_ui_dbus_send_asr_result(pid_t pid, int event, const char* asr_result)
880 {
881         if (0 != __dbus_check()) {
882                 return -1; //MAS_ERROR_OPERATION_FAILED;
883         }
884
885         DBusMessage* msg;
886
887         msg = dbus_message_new_method_call(
888                         MA_UI_CLIENT_SERVICE_NAME,
889                         MA_UI_CLIENT_SERVICE_OBJECT_PATH,
890                         MA_UI_CLIENT_SERVICE_INTERFACE,
891                         MAS_UI_METHOD_SEND_ASR_RESULT);
892
893         if (NULL == msg) {
894                 MAS_LOGE("@@ Request multi-assistant send ASR result : Fail to make message");
895                 return -1; //MA_ERROR_OPERATION_FAILED;
896         } else {
897                 MAS_LOGD("[DEBUG] multi-assistant send ASR result, asr_result(%p)", asr_result);
898         }
899
900         char* temp_asr_result = NULL;
901         if (!asr_result)
902                 temp_asr_result = strdup("#NULL");
903         else
904                 temp_asr_result = strdup(asr_result);
905
906         dbus_message_append_args(msg,
907                 DBUS_TYPE_INT32, &pid,
908                 DBUS_TYPE_INT32, &event,
909                 DBUS_TYPE_STRING, &temp_asr_result,
910                 DBUS_TYPE_INVALID);
911
912         dbus_message_set_no_reply(msg, TRUE);
913
914         if (1 != dbus_connection_send(mConnectionSender, msg, NULL)) {
915                 MAS_LOGE("[Dbus ERROR] Fail to Send");
916                 if (NULL != temp_asr_result) {
917                         free(temp_asr_result);
918                         temp_asr_result = NULL;
919                 }
920                 return -1; // MAS_ERROR_OPERATION_FAILED;
921         } else {
922                 MAS_LOGD("[Dbus DEBUG] Success to Send ASR result");
923                 dbus_connection_flush(mConnectionSender);
924         }
925
926         dbus_message_unref(msg);
927
928         if (temp_asr_result)
929                 free(temp_asr_result);
930         return 0;
931 }
932
933 int CServiceIpcDbus::masc_ui_dbus_send_result(pid_t pid, const char* display_text, const char* utterance_text, const char* result_json)
934 {
935         if (0 != __dbus_check()) {
936                 return -1; //MA_ERROR_OPERATION_FAILED;
937         }
938
939         DBusMessage* msg;
940
941         msg = dbus_message_new_method_call(
942                         MA_UI_CLIENT_SERVICE_NAME,
943                         MA_UI_CLIENT_SERVICE_OBJECT_PATH,
944                         MA_UI_CLIENT_SERVICE_INTERFACE,
945                         MAS_UI_METHOD_SEND_RESULT);
946
947         if (NULL == msg) {
948                 MAS_LOGE("@@ Request multi-assistant send result : Fail to make message");
949                 return -1; //MA_ERROR_OPERATION_FAILED;
950         } else {
951                 MAS_LOGD("[DEBUG] multi-assistant send result");
952         }
953         char* temp_display_text = NULL;
954         char* temp_utterance_text = NULL;
955         char* temp_result_json = NULL;
956
957 #if 0
958         dbus_message_append_args(msg,
959                 DBUS_TYPE_INT32, &pid,
960                 DBUS_TYPE_STRING, &display_text,
961                 DBUS_TYPE_STRING, &utterance_text,
962                 DBUS_TYPE_STRING, &result_json,
963                 DBUS_TYPE_INVALID);
964
965         dbus_message_set_no_reply(msg, TRUE);
966
967         if (1 != dbus_connection_send(mConnectionSender, msg, NULL)) {
968                 MAS_LOGE("[Dbus ERROR] Fail to Send");
969                 return -1; //MA_ERROR_OPERATION_FAILED;
970         } else {
971                 MAS_LOGD("[Dbus DEBUG] Success to Send result");
972                 dbus_connection_flush(mConnectionSender);
973         }
974
975         dbus_message_unref(msg);
976 #else
977         if (!display_text)
978                 temp_display_text = strdup("#NULL");
979         else
980                 temp_display_text = strdup(display_text);
981         if (!utterance_text)
982                 temp_utterance_text = strdup("#NULL");
983         else
984                 temp_utterance_text = strdup(utterance_text);
985         if (!result_json)
986                 temp_result_json = strdup("#NULL");
987         else
988                 temp_result_json = strdup(result_json);
989
990         dbus_message_append_args(msg,
991                 DBUS_TYPE_INT32, &pid,
992                 DBUS_TYPE_STRING, &temp_display_text,
993                 DBUS_TYPE_STRING, &temp_utterance_text,
994                 DBUS_TYPE_STRING, &temp_result_json,
995                 DBUS_TYPE_INVALID);
996
997         dbus_message_set_no_reply(msg, TRUE);
998
999         if (1 != dbus_connection_send(mConnectionSender, msg, NULL)) {
1000                 MAS_LOGE("[Dbus ERROR] Fail to Send");
1001                 if (temp_display_text)
1002                         free(temp_display_text);
1003                 if (temp_utterance_text)
1004                         free(temp_utterance_text);
1005                 if (temp_result_json)
1006                         free(temp_result_json);
1007                 return -1; //MA_ERROR_OPERATION_FAILED;
1008         } else {
1009                 MAS_LOGD("[Dbus DEBUG] Success to Send result");
1010                 dbus_connection_flush(mConnectionSender);
1011         }
1012
1013         dbus_message_unref(msg);
1014
1015         if (temp_display_text)
1016                 free(temp_display_text);
1017         if (temp_utterance_text)
1018                 free(temp_utterance_text);
1019         if (temp_result_json)
1020                 free(temp_result_json);
1021 #endif
1022         return 0;
1023 }
1024
1025 int CServiceIpcDbus::masc_ui_dbus_change_assistant(const char* app_id)
1026 {
1027         if (0 != __dbus_check()) {
1028                 return -1; //MAS_ERROR_OPERATION_FAILED;
1029         }
1030
1031         if (NULL == app_id) {
1032                 MAS_LOGE("@@ Request multi-assistant send change assistant request : Fail to make message");
1033                 return -1; //MA_ERROR_OPERATION_FAILED;
1034         } else {
1035                 MAS_LOGD("[DEBUG] multi-assistant send change assistant request app_id(%s)", app_id);
1036         }
1037
1038         DBusMessage* msg;
1039
1040         msg = dbus_message_new_method_call(
1041                         MA_UI_CLIENT_SERVICE_NAME,
1042                         MA_UI_CLIENT_SERVICE_OBJECT_PATH,
1043                         MA_UI_CLIENT_SERVICE_INTERFACE,
1044                         MAS_UI_METHOD_CHANGE_ASSISTANT);
1045
1046         dbus_message_append_args(msg,
1047                 DBUS_TYPE_STRING, &app_id,
1048                 DBUS_TYPE_INVALID);
1049
1050         dbus_message_set_no_reply(msg, TRUE);
1051
1052         if (1 != dbus_connection_send(mConnectionSender, msg, NULL)) {
1053                 MAS_LOGE("[Dbus ERROR] Fail to Send");
1054                 return -1; // MAS_ERROR_OPERATION_FAILED;
1055         } else {
1056                 MAS_LOGD("[Dbus DEBUG] Success to Send change assistant request");
1057                 dbus_connection_flush(mConnectionSender);
1058         }
1059
1060         dbus_message_unref(msg);
1061
1062         return 0;
1063 }
1064
1065 int CServiceIpcDbus::masc_ui_dbus_send_error_message(int reason, const char* err_msg)
1066 {
1067         if (NULL == mConnectionSender) {
1068                 MAS_LOGE("[Dbus ERROR] Dbus connection is not available");
1069                 return -1;
1070         }
1071
1072         DBusMessage* msg = NULL;
1073
1074         /* create a message */
1075         msg = dbus_message_new_signal(
1076                 MA_UI_CLIENT_SERVICE_OBJECT_PATH,       /* object name of the signal */
1077                 MA_UI_CLIENT_SERVICE_INTERFACE,         /* interface name of the signal */
1078                 MAS_UI_METHOD_ERROR);                           /* name of the signal */
1079
1080         if (NULL == msg) {
1081                 MAS_LOGE("[Dbus ERROR] Fail to create error message");
1082                 return -1;
1083         }
1084
1085         char* temp_err_msg = NULL;
1086
1087         if (err_msg)
1088                 temp_err_msg = strdup(err_msg);
1089         else
1090                 temp_err_msg = strdup("#NULL");
1091
1092         dbus_message_append_args(msg,
1093                 DBUS_TYPE_INT32, &reason,
1094                 DBUS_TYPE_STRING, &temp_err_msg,
1095                 DBUS_TYPE_INVALID);
1096
1097         dbus_message_set_no_reply(msg, TRUE);
1098
1099         if (!dbus_connection_send(mConnectionSender, msg, NULL)) {
1100                 MAS_LOGE("[Dbus ERROR] <<<< error message : Out Of Memory !");
1101         } else {
1102                 MAS_LOGD("<<<< Send error message : reason(%d), err_msg(%s)", reason, temp_err_msg);
1103                 dbus_connection_flush(mConnectionSender);
1104         }
1105
1106         dbus_message_unref(msg);
1107
1108         if (temp_err_msg)
1109                 free(temp_err_msg);
1110         return 0;
1111 }
1112
1113 int CServiceIpcDbus::masc_ui_dbus_send_recognition_result(pid_t pid, int result)
1114 {
1115         if (0 != __dbus_check()) {
1116                 return -1; //MAS_ERROR_OPERATION_FAILED;
1117         }
1118
1119         DBusMessage* msg;
1120
1121         msg = dbus_message_new_method_call(
1122                         MA_UI_CLIENT_SERVICE_NAME,
1123                         MA_UI_CLIENT_SERVICE_OBJECT_PATH,
1124                         MA_UI_CLIENT_SERVICE_INTERFACE,
1125                         MAS_UI_METHOD_SEND_RECOGNITION_RESULT);
1126
1127         if (NULL == msg) {
1128                 MAS_LOGE("@@ Request multi-assistant send recognition result : Fail to make message");
1129                 return -1; //MA_ERROR_OPERATION_FAILED;
1130         } else {
1131                 MAS_LOGD("[DEBUG] multi-assistant send recognition result(%d)", result);
1132         }
1133
1134         dbus_message_append_args(msg,
1135                 DBUS_TYPE_INT32, &pid,
1136                 DBUS_TYPE_INT32, &result,
1137                 DBUS_TYPE_INVALID);
1138
1139         dbus_message_set_no_reply(msg, TRUE);
1140
1141         if (1 != dbus_connection_send(mConnectionSender, msg, NULL)) {
1142                 MAS_LOGE("[Dbus ERROR] Fail to Send");
1143                 return -1; // MAS_ERROR_OPERATION_FAILED;
1144         } else {
1145                 MAS_LOGD("[Dbus DEBUG] Success to Send ASR result");
1146                 dbus_connection_flush(mConnectionSender);
1147         }
1148
1149         dbus_message_unref(msg);
1150
1151         return 0;
1152 }
1153
1154 int CServiceIpcDbus::masc_ui_dbus_enable_common_ui(int enable)
1155 {
1156         if (0 != __dbus_check()) {
1157                 return -1; //MAS_ERROR_OPERATION_FAILED;
1158         }
1159
1160         DBusMessage* msg;
1161
1162         msg = dbus_message_new_method_call(
1163                         MA_UI_CLIENT_SERVICE_NAME,
1164                         MA_UI_CLIENT_SERVICE_OBJECT_PATH,
1165                         MA_UI_CLIENT_SERVICE_INTERFACE,
1166                         MAS_UI_METHOD_ENABLE_COMMON_UI);
1167
1168         if (NULL == msg) {
1169                 MAS_LOGE("@@ Request multi-assistant enable common ui : Fail to make message");
1170                 return -1; //MA_ERROR_OPERATION_FAILED;
1171         } else {
1172                 MAS_LOGD("[DEBUG] multi-assistant enable common ui (%d)", enable);
1173         }
1174
1175         dbus_message_append_args(msg,
1176                 DBUS_TYPE_INT32, &enable,
1177                 DBUS_TYPE_INVALID);
1178
1179         dbus_message_set_no_reply(msg, TRUE);
1180
1181         if (1 != dbus_connection_send(mConnectionSender, msg, NULL)) {
1182                 MAS_LOGE("[Dbus ERROR] Fail to Send");
1183                 return -1; // MAS_ERROR_OPERATION_FAILED;
1184         } else {
1185                 MAS_LOGD("[Dbus DEBUG] Success to Send ASR result");
1186                 dbus_connection_flush(mConnectionSender);
1187         }
1188
1189         dbus_message_unref(msg);
1190
1191         return 0;
1192 }
1193
1194 static void print_duration(int num_messages, std::chrono::time_point<std::chrono::steady_clock> started)
1195 {
1196         const std::chrono::milliseconds threshold(100);
1197         auto finished = std::chrono::steady_clock::now();
1198         auto interval = finished - started;
1199         if (interval > threshold) {
1200                 long long int count = static_cast<long long int>(
1201                         std::chrono::duration_cast<std::chrono::milliseconds>(interval).count());
1202                 MAS_LOGE("DBus messages processed : %d, %lld", num_messages, count);
1203         }
1204 }
1205
1206 static Eina_Bool listener_event_callback(void* data, Ecore_Fd_Handler *fd_handler)
1207 {
1208         int num_messages = 0;
1209         auto started = std::chrono::steady_clock::now();
1210
1211         CServiceIpcDbus* service_ipc = static_cast<CServiceIpcDbus*>(data);
1212         if (NULL == service_ipc) {
1213                 MAS_LOGE("Error : service_ipc NULL");
1214                 print_duration(num_messages, started);
1215                 return ECORE_CALLBACK_RENEW;
1216         }
1217
1218         DBusConnection* mConnectionListener = service_ipc->get_connection_listener();
1219         if (NULL == mConnectionListener) {
1220                 MAS_LOGE("Error : mConnectionListener NULL");
1221                 print_duration(num_messages, started);
1222                 return ECORE_CALLBACK_RENEW;
1223         }
1224
1225         CServiceIpcDbusDispatcher* dispatcher = service_ipc->get_dispatcher();
1226         if (NULL == dispatcher) {
1227                 MAS_LOGE("Error : dispatcher NULL");
1228                 print_duration(num_messages, started);
1229                 return ECORE_CALLBACK_RENEW;
1230         }
1231
1232         dbus_connection_read_write_dispatch(mConnectionListener, 50);
1233
1234         while (1) {
1235                 DBusMessage* msg = NULL;
1236                 msg = dbus_connection_pop_message(mConnectionListener);
1237
1238                 if (TRUE != dbus_connection_get_is_connected(mConnectionListener)) {
1239                         MAS_LOGE("[ERROR] Connection is disconnected");
1240                         print_duration(num_messages, started);
1241                         return ECORE_CALLBACK_RENEW;
1242                 }
1243
1244                 /* loop again if we haven't read a message */
1245                 if (NULL == msg) {
1246                         print_duration(num_messages, started);
1247                         return ECORE_CALLBACK_RENEW;
1248                 }
1249
1250                 /* client event */
1251                 if (dbus_message_is_method_call(msg, MA_SERVER_SERVICE_INTERFACE, MA_METHOD_HELLO)) {
1252                         dispatcher->on_hello(mConnectionListener, msg);
1253
1254                 } else if (dbus_message_is_method_call(msg, MA_SERVER_SERVICE_INTERFACE, MA_METHOD_INITIALIZE)) {
1255                         dispatcher->on_initialize(mConnectionListener, msg);
1256
1257                 } else if (dbus_message_is_method_call(msg, MA_SERVER_SERVICE_INTERFACE, MA_METHOD_DEINITIALIZE)) {
1258                         dispatcher->on_deinitialize(mConnectionListener, msg);
1259
1260                 } else if (dbus_message_is_method_call(msg, MA_SERVER_SERVICE_INTERFACE, MA_METHOD_GET_RECORDING_AUDIO_FORMAT)) {
1261                         dispatcher->on_get_audio_format(mConnectionListener, msg);
1262
1263                 } else if (dbus_message_is_method_call(msg, MA_SERVER_SERVICE_INTERFACE, MA_METHOD_GET_RECORDING_AUDIO_SOURCE_TYPE)) {
1264                         dispatcher->on_get_audio_source_type(mConnectionListener, msg);
1265
1266                 } else if (dbus_message_is_method_call(msg, MA_SERVER_SERVICE_INTERFACE, MA_METHOD_SEND_ASR_RESULT)) {
1267                         dispatcher->on_send_asr_result(mConnectionListener, msg);
1268
1269                 } else if (dbus_message_is_method_call(msg, MA_SERVER_SERVICE_INTERFACE, MA_METHOD_SEND_RESULT)) {
1270                         dispatcher->on_send_result(mConnectionListener, msg);
1271
1272                 } else if (dbus_message_is_method_call(msg, MA_SERVER_SERVICE_INTERFACE, MA_METHOD_SEND_RECOGNITION_RESULT)) {
1273                         dispatcher->on_send_recognition_result(mConnectionListener, msg);
1274
1275                 } else if (dbus_message_is_method_call(msg, MA_SERVER_SERVICE_INTERFACE, MA_METHOD_START_STREAMING_AUDIO_DATA)) {
1276                         /* Reset mileage data for logging */
1277                         gAudioDataMileage.store(0);
1278                         dispatcher->on_start_streaming_audio_data(mConnectionListener, msg);
1279
1280                 } else if (dbus_message_is_method_call(msg, MA_SERVER_SERVICE_INTERFACE, MA_METHOD_STOP_STREAMING_AUDIO_DATA)) {
1281                         dispatcher->on_stop_streaming_audio_data(mConnectionListener, msg);
1282
1283                 } else if (dbus_message_is_method_call(msg, MA_SERVER_SERVICE_INTERFACE, MA_METHOD_UPDATE_VOICE_FEEDBACK_STATE)) {
1284                         dispatcher->on_update_voice_feedback_state(mConnectionListener, msg);
1285
1286                 } else if (dbus_message_is_method_call(msg, MA_SERVER_SERVICE_INTERFACE, MA_METHOD_SEND_ASSISTANT_SPECIFIC_COMMAND)) {
1287                         dispatcher->on_send_assistant_specific_command(mConnectionListener, msg);
1288
1289                 } else if (dbus_message_is_method_call(msg, MA_SERVER_SERVICE_INTERFACE, MA_METHOD_SET_BACKGROUND_VOLUME)) {
1290                         dispatcher->on_set_background_volume(mConnectionListener, msg);
1291
1292                 } else if (dbus_message_is_method_call(msg, MA_SERVER_SERVICE_INTERFACE, MA_METHOD_SET_PREPROCESSING_ALLOW_MODE)) {
1293                         dispatcher->on_set_preprocessing_allow_mode(mConnectionListener, msg);
1294
1295                 } else if (dbus_message_is_method_call(msg, MA_SERVER_SERVICE_INTERFACE, MA_METHOD_SEND_PREPROCESSING_RESULT)) {
1296                         dispatcher->on_send_preprocessing_result(mConnectionListener, msg);
1297
1298                 } else if (dbus_message_is_method_call(msg, MA_SERVER_SERVICE_INTERFACE, MA_METHOD_SET_WAKE_WORD_AUDIO_REQUIRE_FLAG)) {
1299                         dispatcher->on_set_wake_word_audio_require_flag(mConnectionListener, msg);
1300
1301                 } else if (dbus_message_is_method_call(msg, MA_SERVER_SERVICE_INTERFACE, MA_METHOD_SET_ASSISTANT_WAKEUP_LANGUAGE)) {
1302                         dispatcher->on_set_assistant_language(mConnectionListener, msg);
1303
1304                 } else if (dbus_message_is_method_call(msg, MA_SERVER_SERVICE_INTERFACE, MA_METHOD_ADD_WAKE_WORD)) {
1305                         dispatcher->on_add_wake_word(mConnectionListener, msg);
1306
1307                 } else if (dbus_message_is_method_call(msg, MA_SERVER_SERVICE_INTERFACE, MA_METHOD_REMOVE_WAKE_WORD)) {
1308                         dispatcher->on_remove_wake_word(mConnectionListener, msg);
1309
1310                 } else if (dbus_message_is_method_call(msg, MA_SERVER_SERVICE_INTERFACE, MA_UI_METHOD_INITIALIZE)) {
1311                         dispatcher->on_ui_initialize(mConnectionListener, msg);
1312
1313                 } else if (dbus_message_is_method_call(msg, MA_SERVER_SERVICE_INTERFACE, MA_UI_METHOD_DEINITIALIZE)) {
1314                         dispatcher->on_ui_deinitialize(mConnectionListener, msg);
1315
1316                 } else if (dbus_message_is_method_call(msg, MA_SERVER_SERVICE_INTERFACE, MA_UI_METHOD_CHANGE_ASSISTANT)) {
1317                         dispatcher->on_ui_change_assistant(mConnectionListener, msg);
1318
1319                 } else {
1320                         MAS_LOGE("Message is NOT valid");
1321                         /* Invalid method */
1322                 }
1323                 /* free the message */
1324                 dbus_message_unref(msg);
1325
1326                 num_messages++;
1327         }
1328
1329         print_duration(num_messages, started);
1330         return ECORE_CALLBACK_RENEW;
1331 }
1332
1333 void CServiceIpcDbus::connection_free()
1334 {
1335         if (NULL != mConnectionListener) {
1336                 dbus_connection_close(mConnectionListener);
1337                 dbus_connection_unref(mConnectionListener);
1338                 mConnectionListener = NULL;
1339         }
1340         if (NULL != mConnectionSender) {
1341                 dbus_connection_close(mConnectionSender);
1342                 dbus_connection_unref(mConnectionSender);
1343                 mConnectionSender = NULL;
1344         }
1345 }
1346
1347 int CServiceIpcDbus::open_connection()
1348 {
1349         DBusError err;
1350         dbus_error_init(&err);
1351
1352         int ret;
1353
1354         /* Create connection for sender */
1355         mConnectionSender = dbus_bus_get_private(DBUS_BUS_SESSION, &err);
1356
1357         if (dbus_error_is_set(&err)) {
1358                 MAS_LOGE("[Dbus ERROR] Fail dbus_bus_get : %s", err.message);
1359                 dbus_error_free(&err);
1360         }
1361
1362         if (NULL == mConnectionSender) {
1363                 MAS_LOGE("[Dbus ERROR] Fail to get dbus connection");
1364                 return -1;
1365         }
1366
1367         dbus_connection_set_exit_on_disconnect(mConnectionSender, false);
1368
1369         /* connect to the bus and check for errors */
1370         mConnectionListener = dbus_bus_get_private(DBUS_BUS_SESSION, &err);
1371
1372         if (dbus_error_is_set(&err)) {
1373                 MAS_LOGE("[Dbus ERROR] Fail dbus_bus_get : %s", err.message);
1374                 dbus_error_free(&err);
1375         }
1376
1377         if (NULL == mConnectionListener) {
1378                 MAS_LOGE("[Dbus ERROR] Fail to get dbus connection");
1379                 connection_free();
1380                 return -1;
1381         }
1382
1383         dbus_connection_set_exit_on_disconnect(mConnectionListener, false);
1384
1385         /* request our name on the bus and check for errors */
1386         ret = dbus_bus_request_name(mConnectionListener, MA_SERVER_SERVICE_NAME, DBUS_NAME_FLAG_REPLACE_EXISTING, &err);
1387
1388         if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) {
1389                 printf("Fail to be primary owner in dbus request.");
1390                 MAS_LOGE("[Dbus ERROR] Fail to be primary owner");
1391                 connection_free();
1392                 return -1;
1393         }
1394
1395         if (dbus_error_is_set(&err)) {
1396                 MAS_LOGE("[Dbus ERROR] dbus_bus_request_name() : %s", err.message);
1397                 dbus_error_free(&err);
1398                 connection_free();
1399                 return -1;
1400         }
1401
1402         /* Flush messages which are received before fd event handler registration */
1403         while (DBUS_DISPATCH_DATA_REMAINS == dbus_connection_get_dispatch_status(mConnectionListener)) {
1404                 listener_event_callback(this, NULL);
1405         }
1406
1407         /* add a rule for getting signal */
1408         char rule[128];
1409         snprintf(rule, 128, "type='signal',interface='%s'", MA_SERVER_SERVICE_INTERFACE);
1410
1411         /* add a rule for which messages we want to see */
1412         dbus_bus_add_match(mConnectionListener, rule, &err);/* see signals from the given interface */
1413
1414         if (dbus_error_is_set(&err)) {
1415                 MAS_LOGE("[Dbus ERROR] dbus_bus_add_match() : %s", err.message);
1416                 dbus_error_free(&err);
1417                 connection_free();
1418                 return -1;
1419         }
1420
1421         int fd = 0;
1422         if (1 != dbus_connection_get_unix_fd(mConnectionListener, &fd)) {
1423                 MAS_LOGE("fail to get fd from dbus ");
1424                 connection_free();
1425                 return -1;
1426         } else {
1427                 MAS_LOGD("Get fd from dbus : %d", fd);
1428         }
1429
1430         mFdHandler = ecore_main_fd_handler_add(fd, ECORE_FD_READ, (Ecore_Fd_Cb)listener_event_callback, this, NULL, NULL);
1431
1432         if (NULL == mFdHandler) {
1433                 MAS_LOGE("[Dbus ERROR] Fail to get fd handler");
1434                 connection_free();
1435                 return -1;
1436         }
1437
1438 #if USE_TRUSTED_MESSAGE_PORT
1439         int port_id = message_port_register_trusted_local_port(mLocalMessagePortName.c_str(), message_port_cb, this);
1440 #else
1441         int port_id = message_port_register_local_port(mLocalMessagePortName.c_str(), message_port_cb, this);
1442 #endif
1443
1444         if (port_id < 0) {
1445                 MAS_LOGE("Port register error: %d", port_id);
1446         } else {
1447                 MAS_LOGI("port_id: %d", port_id);
1448                 mLocalMessagePortID = port_id;
1449         }
1450
1451         return 0;
1452 }
1453
1454 int CServiceIpcDbus::close_connection()
1455 {
1456 #if USE_TRUSTED_MESSAGE_PORT
1457         if (-1 != mLocalMessagePortID) message_port_unregister_trusted_local_port(mLocalMessagePortID);
1458 #else
1459         if (-1 != mLocalMessagePortID) message_port_unregister_local_port(mLocalMessagePortID);
1460 #endif
1461         mLocalMessagePortID = -1;
1462
1463         DBusError err;
1464         dbus_error_init(&err);
1465
1466         if (NULL != mFdHandler) {
1467                 ecore_main_fd_handler_del(mFdHandler);
1468                 mFdHandler = NULL;
1469         }
1470
1471         if (NULL != mConnectionListener) {
1472                 dbus_bus_release_name(mConnectionListener, MA_SERVER_SERVICE_NAME, &err);
1473                 if (dbus_error_is_set(&err)) {
1474                         MAS_LOGE("[Dbus ERROR] dbus_bus_release_name() : %s", err.message);
1475                         dbus_error_free(&err);
1476                 }
1477         } else {
1478                 MAS_LOGE("mConnectionListener is NULL!!");
1479         }
1480
1481         connection_free();
1482
1483         return 0;
1484 }