Fix to cast from pointer to integer safely
[platform/core/connectivity/bluetooth-agent.git] / ag-agent / bluetooth-ag-agent.c
1 /*
2  * Bluetooth-ag-agent
3  *
4  * Copyright (c) 2014 - 2015 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact:     Hocheol Seo <hocheol.seo@samsung.com>
7  *              Chethan T N <chethan.tn@samsung.com>
8  *              Chanyeol Park <chanyeol.park@samsung.com>
9  *              Rakesh MK <rakesh.mk@samsung.com>
10  *
11  * Licensed under the Apache License, Version 2.0 (the "License");
12  * you may not use this file except in compliance with the License.
13  * You may obtain a copy of the License at
14  *
15  *              http://www.apache.org/licenses/LICENSE-2.0
16  *
17  * Unless required by applicable law or agreed to in writing, software
18  * distributed under the License is distributed on an "AS IS" BASIS,
19  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20  * See the License for the specific language governing permissions and
21  * limitations under the License.
22  *
23  */
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <signal.h>
27 #include <sys/poll.h>
28 #include <gio/gunixfdlist.h>
29 #include <bundle_internal.h>
30 #include "bluetooth-ag-agent.h"
31 #include "bluetooth-ag-handler.h"
32 #include "bluetooth-agent-profile.h"
33
34 #include <TapiUtility.h>
35 #include <ITapiSim.h>
36 #include <ITapiModem.h>
37 #include <TelNetwork.h>
38 #include <app.h>
39 #include <aul.h>
40 #include <system_info.h>
41
42 #include "contacts.h"
43 #include "appsvc.h"
44
45 static GMainLoop *gmain_loop = NULL;
46 static GDBusProxy *service_gproxy;
47 static guint interface_added_sig_id = 0;
48 static guint interface_removed_sig_id = 0;
49 static guint name_owner_sig_id = 0;
50 GDBusConnection *ag_dbus_conn = NULL;
51 gchar *remote_dev_path = NULL;
52 gboolean wbs_en;
53 uint16_t hfp_ver;
54 uint16_t hsp_ver;
55 static TapiHandle *tapi_handle;
56 extern wbs_options wbs_opts;
57 GSList *active_devices = NULL;
58 static gchar *local_addr = NULL;
59 static GDBusProxy *app_gproxy;
60 static gboolean call_launch_requested = FALSE;
61 static gchar* sco_owner = NULL;
62 static guint sco_open_timer_id = 0;
63 static gboolean sco_open_request = FALSE;
64 static guint hf_bluez_id;
65 static guint hs_bluez_id;
66 static guint app_id;
67 #ifdef TIZEN_FEATURE_BT_MEDIA_ENHANCE
68 static guint media_sig_id = 0;
69 static guint media_state_sig_id = 0;
70 static bt_ag_media_transport_state_t transport_state;
71 #endif
72
73 #define HSP_AG_UUID "00001112-0000-1000-8000-00805f9b34fb"
74 #define HFP_AG_UUID "0000111f-0000-1000-8000-00805f9b34fb"
75 #ifdef TIZEN_FEATURE_BT_MEDIA_ENHANCE
76 #define A2DP_SINK_UUID "0000110b-0000-1000-8000-00805f9b34fb"
77 #endif
78 #define DEFAULT_ADAPTER_OBJECT_PATH "/org/bluez/hci0"
79 #define VCONF_KEY_BT_LUNAR_ENABLED "db/wms/bt_loop_device_hfp_connected"
80
81 #if defined(TIZEN_PROFILE_WEARABLE) && defined(TIZEN_FEATURE_BT_HFP_AG)
82 #define CALL_APP_ID "org.tizen.call-ui"
83 #endif
84
85 #if defined(TIZEN_SUPPORT_DUAL_HF)
86 #define VCONF_KEY_BT_HOST_BT_MAC_ADDR "db/wms/host_bt_mac"
87 #define MAX_CONNECTED_DEVICES 2
88 #else
89 #define MAX_CONNECTED_DEVICES 1
90 #endif
91
92 #define BT_AG_SIG_NUM 3
93 static struct sigaction bt_ag_sigoldact[BT_AG_SIG_NUM];
94 static int bt_ag_sig_to_handle[] = { SIGABRT, SIGSEGV, SIGTERM };
95
96 /*Below Inrospection data is exposed to bluez from agent*/
97 static const gchar ag_agent_bluez_introspection_xml[] =
98 "<node name='/'>"
99 " <interface name='org.bluez.Profile1'>"
100 "     <method name='NewConnection'>"
101 "          <arg type='o' name='device' direction='in'/>"
102 "          <arg type='h' name='fd' direction='in'/>"
103 "          <arg type='a{sv}' name='options' direction='in'/>"
104 "     </method>"
105 "     <method name='RequestDisconnection'>"
106 "          <arg type='o' name='device' direction='in'/>"
107 "     </method>"
108 " </interface>"
109 "</node>";
110
111 /*Below Introspection data is exposed to application from agent*/
112 static const gchar ag_agent_app_introspection_xml[] =
113 "<node name='/'>"
114 "  <interface name='Org.Hfp.App.Interface'>"
115 "     <method name='RegisterApplication'>"
116 "          <arg type='s' name='path' direction='in'/>"
117 "          <arg type='s' name='address' direction='in'/>"
118 "     </method>"
119 "     <method name='UnregisterApplication'>"
120 "          <arg type='s' name='path' direction='in'/>"
121 "     </method>"
122 "     <method name='IncomingCall'>"
123 "          <arg type='s' name='path' direction='in'/>"
124 "          <arg type='s' name='number' direction='in'/>"
125 "          <arg type='i' name='id' direction='in'/>"
126 "     </method>"
127 "     <method name='OutgoingCall'>"
128 "          <arg type='s' name='path' direction='in'/>"
129 "          <arg type='s' name='number' direction='in'/>"
130 "          <arg type='i' name='id' direction='in'/>"
131 "     </method>"
132 "     <method name='ChangeCallStatus'>"
133 "          <arg type='s' name='path' direction='in'/>"
134 "          <arg type='s' name='number' direction='in'/>"
135 "          <arg type='i' name='status' direction='in'/>"
136 "          <arg type='i' name='id' direction='in'/>"
137 "     </method>"
138 "     <method name='GetProperties'>"
139 "               <arg type='a{sv}' name='properties' direction='out'/>"
140 "     </method>"
141 "       <method name='Disconnect'>"
142 "       </method>"
143 "       <method name='IsConnected'>"
144 "               <arg type='b' name='connected' direction='out'/>"
145 "       </method>"
146 "       <method name='IndicateCall'>"
147 "       </method>"
148 "       <method name='CancelCall'>"
149 "       </method>"
150 "       <method name='Play'>"
151 "       </method>"
152 "       <method name='Stop'>"
153 "       </method>"
154 "       <method name='IsPlaying'>"
155 "       <arg type='b' name='playing' direction='out'/>"
156 "       </method>"
157 "       <method name='GetSpeakerGain'>"
158 "               <arg type='q' name='gain' direction='out'/>"
159 "       </method>"
160 "       <method name='GetMicrophoneGain'>"
161 "               <arg type='q' name='gain' direction='out'/>"
162 "       </method>"
163 "       <method name='SetSpeakerGain'>"
164 "               <arg type='q' name='gain' direction='in'/>"
165 "       </method>"
166 "       <method name='SetMicrophoneGain'>"
167 "               <arg type='q' name='gain' direction='in'/>"
168 "       </method>"
169 "       <method name='SetVoiceDial'>"
170 "               <arg type='b' name='enable' direction='in'/>"
171 "       </method>"
172 "       <method name='CheckPrivilege'>"
173 "       </method>"
174 "     <method name='SwapHeadset'>"
175 "          <arg type='s' name='remote_addr' direction='in'/>"
176 "     </method>"
177 "  </interface>"
178 "</node>";
179
180 struct event {
181         const char *cmd;
182         int (*callback)(bt_ag_info_t *hs, const char *buf);
183 };
184
185 struct sco_socket_addr {
186         sa_family_t     sco_family;
187         bt_addr         sco_bdaddr;
188 };
189
190 typedef struct {
191         uint16_t setting;
192 } bt_voice;
193
194 struct ag_codec {
195         bt_ag_info_t *bt_ag_info;
196         char *codec_status;
197 };
198
199 bt_ag_status_t ag = {
200         .telephony_ready = FALSE,
201         .features = 0,
202         .er_mode = 3,
203         .er_ind = 0,
204         .rh = BT_RSP_HOLD_NOT_SUPPORTED,
205         .number = NULL,
206         .number_type = 0,
207         .ring_timer = 0,
208         .sdp_features = 0,
209 };
210 static void __bt_ag_agent_sigterm_handler(int signo);
211 static gboolean __bt_ag_agent_connection(gint32 fd, const gchar *device_path,
212                                                 const gchar *object_path);
213 static gboolean __bt_ag_agent_connection_release(bt_ag_info_t *hs);
214 static gboolean __bt_ag_event_handler(GIOChannel *channel, GIOCondition cond,
215         void *user_data);
216 static int __bt_ag_sco_connect(bt_ag_info_t *hs);
217 void _bt_ag_set_headset_state(bt_ag_info_t *hs, hs_state_t state);
218 static void __bt_ag_agent_reg_sim_event(TapiHandle *handle, void *user_data);
219 static void __bt_ag_agent_dereg_sim_event(TapiHandle *handle);
220 static void __bt_ag_name_owner_changed_cb(GDBusConnection *connection,
221                                         const gchar *sender_name,
222                                         const gchar *object_path,
223                                         const gchar *interface_name,
224                                         const gchar *signal_name,
225                                         GVariant *parameters,
226                                         gpointer user_data);
227
228 /* LCOV_EXCL_START */
229 static void __bt_convert_addr_type_to_rev_string(char *address,
230                                 unsigned char *addr)
231 {
232         ret_if(address == NULL);
233         ret_if(addr == NULL);
234
235         g_snprintf(address, BT_ADDRESS_STRING_SIZE,
236                         "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
237                         addr[5], addr[4], addr[3], addr[2], addr[1], addr[0]);
238 }
239
240 static GDBusProxy *__bt_ag_gdbus_init_service_proxy(const gchar *service,
241                                 const gchar *path, const gchar *interface)
242 {
243         FN_START;
244
245         GDBusProxy *proxy;
246         GError *err = NULL;
247
248         if (ag_dbus_conn == NULL)
249                 ag_dbus_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
250
251         if (!ag_dbus_conn) {
252                 if (err) {
253                         ERR("Unable to connect to gdbus: %s", err->message);
254                         g_clear_error(&err);
255                 }
256                 return NULL;
257         }
258
259         proxy =  g_dbus_proxy_new_sync(ag_dbus_conn,
260                         G_DBUS_PROXY_FLAGS_NONE, NULL,
261                         service, path,
262                         interface, NULL, &err);
263
264         if (!proxy) {
265                 if (err) {
266                         ERR("Unable to create proxy: %s", err->message);
267                         g_clear_error(&err);
268                 }
269                 return NULL;
270         }
271
272         FN_END;
273         return proxy;
274 }
275
276 static GDBusProxy *__bt_ag_gdbus_get_app_proxy(const gchar *service,
277                                 const gchar *path, const gchar *interface)
278 {
279         return (app_gproxy) ? app_gproxy :
280                         __bt_ag_gdbus_init_service_proxy(service,
281                                         path, interface);
282 }
283
284 static int __bt_ag_agent_gdbus_method_send(const char *service,
285                                 const gchar *path, const char *interface,
286                                 const char *method, gboolean response,
287                                 GVariant *parameters)
288 {
289         FN_START;
290
291         GVariant *ret;
292         GDBusProxy *proxy;
293         GError *error = NULL;
294
295         proxy = __bt_ag_gdbus_get_app_proxy(service, path, interface);
296         if (!proxy)
297                 return BT_HFP_AGENT_ERROR_INTERNAL;
298
299         if (response) {
300                 ret = g_dbus_proxy_call_sync(proxy,
301                                         method, parameters,
302                                         G_DBUS_CALL_FLAGS_NONE, -1,
303                                         NULL, &error);
304                 if (ret == NULL) {
305                         /* dBUS-RPC is failed */
306                         ERR("dBUS-RPC is failed");
307                         if (error != NULL) {
308                                 /* dBUS gives error cause */
309                                 ERR("D-Bus API failure: errCode[%x], message[%s]",
310                                         error->code, error->message);
311
312                                 g_clear_error(&error);
313                         }
314                         return BT_HFP_AGENT_ERROR_INTERNAL;
315                 }
316
317                 g_variant_unref(ret);
318         } else {
319                 g_dbus_proxy_call(proxy,
320                                         method, parameters,
321                                         G_DBUS_CALL_FLAGS_NONE, 2000,
322                                         NULL, NULL, NULL);
323         }
324         return BT_HFP_AGENT_ERROR_NONE;
325 }
326 /* LCOV_EXCL_STOP */
327
328 gboolean _bt_ag_agent_emit_signal(
329                                 GDBusConnection *connection,
330                                 const char *path,
331                                 const char *interface,
332                                 const char *name,
333                                 GVariant *property)
334 {
335         FN_START;
336
337         GError *error = NULL;
338         gboolean ret;
339         ret =  g_dbus_connection_emit_signal(connection,
340                                 NULL, path, interface,
341                                 name, property,
342                                 &error);
343         if (!ret) {
344                 if (error != NULL) {
345                         /* LCOV_EXCL_START */
346                         /* dBUS gives error cause */
347                         ERR("D-Bus API failure: errCode[%x], message[%s]",
348                                 error->code, error->message);
349                         g_clear_error(&error);
350                         /* LCOV_EXCL_STOP */
351                 }
352         }
353         INFO_C("Emit Signal done = [%s]", name);
354
355         FN_END;
356         return ret;
357 }
358
359 gboolean _bt_ag_agent_emit_property_changed(
360                                 GDBusConnection *connection,
361                                 const char *path,
362                                 const char *interface,
363                                 const char *name,
364                                 GVariant *property)
365 {
366         FN_START;
367
368         gboolean ret;
369         GVariant *var_data;
370
371         var_data = g_variant_new("(sv)",        name, property);
372
373         ret =  _bt_ag_agent_emit_signal(connection,
374                                 path, interface,
375                                 "PropertyChanged", var_data);
376         FN_END;
377         return ret;
378 }
379
380 /* LCOV_EXCL_START */
381 static void __bt_ag_agent_start_watch(bt_ag_info_t *bt_ag_info)
382 {
383         bt_ag_info->watch_id = g_io_add_watch(bt_ag_info->io_chan,
384                         G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
385                         (GIOFunc) __bt_ag_event_handler, bt_ag_info);
386 }
387
388 static void __bt_ag_agent_remove_watch(guint *watch_id)
389 {
390         DBG("Remove IO watch ID %d", *watch_id);
391         if (*watch_id > 0) {
392                 g_source_remove(*watch_id);
393                 *watch_id = 0;
394         }
395 }
396
397 #if defined(TIZEN_SUPPORT_DUAL_HF)
398 gboolean __bt_ag_agent_is_companion_device(const char *addr)
399 {
400 #if defined(TIZEN_PROFILE_WEARABLE)
401         char *host_device_address = NULL;
402         host_device_address = vconf_get_str(VCONF_KEY_BT_HOST_BT_MAC_ADDR);
403
404         if (!host_device_address) {
405                 INFO("Failed to get a companion device address");
406                 return FALSE;
407         }
408
409         if (g_strcmp0(host_device_address, addr) == 0) {
410                 INFO("addr[%s] is companion device", addr);
411                 free(host_device_address);
412                 return TRUE;
413         }
414
415         free(host_device_address);
416
417         return FALSE;
418 #else
419         /* TODO : Need to add companion device check condition for Phone models */
420         return FALSE;
421 #endif
422 }
423
424 void __bt_convert_device_path_to_address(const gchar *device_path,
425                                                 char *device_address)
426 {
427         char address[BT_ADDRESS_STRING_SIZE] = { 0 };
428         char *dev_addr;
429
430         ret_if(device_path == NULL);
431         ret_if(device_address == NULL);
432
433         dev_addr = strstr(device_path, "dev_");
434         if (dev_addr != NULL) {
435                 char *pos = NULL;
436                 dev_addr += 4;
437                 g_strlcpy(address, dev_addr, sizeof(address));
438
439                 while ((pos = strchr(address, '_')) != NULL)
440                         *pos = ':';
441
442                 g_strlcpy(device_address, address, BT_ADDRESS_STRING_SIZE);
443         }
444 }
445
446 static gboolean  __bt_ag_agent_is_companion_device_connected(void)
447 {
448         GSList *l;
449
450         for (l = active_devices ; l; l = l->next) {
451                 bt_ag_info_t *data = l->data;
452
453                 if (data->is_companion_device) {
454                         DBG("Companion device found");
455                         return TRUE;
456                 }
457         }
458
459         return FALSE;
460 }
461
462 gboolean __bt_ag_agent_check_dual_hf_condition(const gchar *device_path)
463 {
464         char device_address[BT_ADDRESS_STRING_SIZE] = { 0 };
465         gboolean is_companion_device;
466
467         __bt_convert_device_path_to_address(device_path, device_address);
468         is_companion_device = __bt_ag_agent_is_companion_device(device_address);
469
470         DBG(" device_address[%s]", device_address);
471         DBG(" is_companion_device[%d]", is_companion_device);
472
473         if (__bt_ag_agent_is_companion_device_connected()) {
474                 if (is_companion_device)
475                         return FALSE;
476         } else {
477                 if (!is_companion_device)
478                         return FALSE;
479         }
480         return TRUE;
481 }
482 #endif /* TIZEN_SUPPORT_DUAL_HF */
483 /* LCOV_EXCL_STOP */
484
485 static gboolean __bt_is_phone_locked(int *phone_lock_state)
486 {
487         FN_START;
488         int ret;
489
490         if (NULL == phone_lock_state)
491                 return FALSE;
492
493         ret = vconf_get_int(VCONFKEY_IDLE_LOCK_STATE, phone_lock_state);
494         if (ret != 0) {
495                 /* LCOV_EXCL_START */
496                 ERR("Failed to read  [%s]\n", VCONFKEY_IDLE_LOCK_STATE);
497                 return FALSE;
498                 /* LCOV_EXCL_STOP */
499         }
500
501         FN_END;
502         return TRUE;
503 }
504
505 static gboolean __bt_get_outgoing_callapp_type(int *callapp_type)
506 {
507         FN_START;
508
509         if (NULL == callapp_type)
510                 return FALSE;
511
512 #if defined(TIZEN_PROFILE_WEARABLE) && defined(TIZEN_FEATURE_BT_HFP_AG)
513         *callapp_type = BT_VOICE_CALL;
514         FN_END;
515         return TRUE;
516 #else
517 #if 0
518         int ret;
519         ret = vconf_get_int(
520                         VCONFKEY_CISSAPPL_OUTGOING_CALL_TYPE_INT,
521                         callapp_type);
522         if (ret != 0) {
523                 ERR("Failed to read  [%s]\n",
524                         VCONFKEY_CISSAPPL_OUTGOING_CALL_TYPE_INT);
525                 return FALSE;
526         }
527
528         INFO(" [%s] = [%d]\n",
529                 VCONFKEY_CISSAPPL_OUTGOING_CALL_TYPE_INT, *callapp_type);
530 #endif
531         /* The vconf value does not include in platform. */
532         *callapp_type = BT_VOICE_CALL;
533         FN_END;
534         return TRUE;
535 #endif
536 }
537
538 static gboolean __bt_get_outgoing_call_condition(int *condition)
539 {
540         FN_START;
541
542         if (NULL == condition)
543                 return FALSE;
544
545 #if defined(TIZEN_PROFILE_WEARABLE) && defined(TIZEN_FEATURE_BT_HFP_AG)
546         *condition = BT_MO_ONLY_UNLOCKED;
547         FN_END;
548         return TRUE;
549 #else
550 #if 0
551         int ret;
552         ret = vconf_get_int(
553                         VCONFKEY_CISSAPPL_OUTGOING_CALL_CONDITIONS_INT,
554                         condition);
555         if (ret != 0) {
556                 ERR("Failed to read  [%s]\n",
557                         VCONFKEY_CISSAPPL_OUTGOING_CALL_CONDITIONS_INT);
558                 return FALSE;
559         }
560 #endif
561         /* The vconf value does not include in platform. */
562         *condition = BT_MO_ONLY_UNLOCKED;
563         FN_END;
564         return TRUE;
565 #endif
566 }
567
568 /* LCOV_EXCL_START */
569 static gboolean  __bt_ag_agent_launch_call_app(const char *number)
570 {
571         FN_START;
572         bundle *b;
573
574         DBG_SECURE("number(%s)", number);
575
576         b = bundle_create();
577         if (NULL == b) {
578                 ERR("bundle_create() Failed");
579                 return FALSE;
580         }
581
582         bundle_add(b, "launch-type", "MO");
583         bundle_add(b, "dial-type", "HEADSET");
584
585         if (strlen(number) != 0)
586                 bundle_add(b, "number", number);
587
588         aul_launch_app_async(CALL_APP_ID, b);
589         bundle_free(b);
590
591         FN_END;
592         return TRUE;
593 }
594
595 static void *__bt_ag_agent_launch_call_req(void *arg)
596 {
597         FN_START;
598         bundle *b = (bundle *)arg;
599         if (appsvc_run_service(b, 0, NULL, NULL) < 0)
600                 ERR("Unable to run app svc");
601         bundle_free(b);
602         call_launch_requested = FALSE;
603         FN_END;
604         return NULL;
605 }
606
607 static gboolean __bt_ag_agent_make_call(const char *number)
608 {
609         FN_START;
610
611         char telnum[BT_MAX_TEL_NUM_STRING];
612         bundle *b;
613         pthread_t thread_id;
614
615         if (TIZEN_PROFILE_WEARABLE)
616                 return __bt_ag_agent_launch_call_app(number);
617
618         if (call_launch_requested == TRUE) {
619                 DBG("Launch request is in progress");
620                 return TRUE;
621         }
622
623         b = bundle_create();
624         if (NULL == b)
625                 return FALSE;
626
627         appsvc_set_operation(b, APPSVC_OPERATION_CALL);
628         snprintf(telnum, sizeof(telnum), "tel:%s", number);
629         appsvc_set_uri(b, telnum);
630         appsvc_add_data(b, "ctindex", "-1");
631
632         call_launch_requested = TRUE;
633         if (pthread_create(&thread_id, NULL,
634                         (void *)&__bt_ag_agent_launch_call_req,
635                                         (void *)b) < 0) {
636                 ERR("pthread_create() is failed");
637                 call_launch_requested = FALSE;
638                 return FALSE;
639         }
640         if (pthread_detach(thread_id) < 0)
641                 ERR("pthread_detach() is failed");
642
643         FN_END;
644         return TRUE;
645 }
646
647 static gboolean __bt_ag_agent_make_video_call(const char *mo_number)
648 {
649         FN_START;
650         bundle *kb;
651
652         kb = bundle_create();
653         if (NULL == kb)
654                 return FALSE;
655
656         bundle_add(kb, "KEY_CALL_TYPE", "MO");
657         bundle_add(kb, "number", mo_number);
658         aul_launch_app("org.tizen.vtmain", kb);
659         bundle_free(kb);
660
661         FN_END;
662         return TRUE;
663 }
664
665 gboolean _bt_ag_agent_answer_call(unsigned int call_id,
666                                 const gchar *path, const gchar *sender)
667 {
668         FN_START;
669
670         if (path == NULL || sender == NULL) {
671                 DBG("Invalid Arguments");
672                 return FALSE;
673         }
674
675         DBG("Application path = %s", path);
676         DBG("Call Id = %d", call_id);
677         DBG("Sender = %s", sender);
678
679         _bt_ag_agent_emit_signal(ag_dbus_conn, path,
680                                         BT_HEADSET_INTERFACE, "Answer",
681                                         g_variant_new("(u)", call_id));
682         FN_END;
683         return TRUE;
684 }
685
686 gboolean _bt_ag_agent_reject_call(unsigned int call_id,
687                                 const gchar *path, const gchar *sender)
688 {
689         FN_START;
690
691         if (path == NULL || sender == NULL) {
692                 DBG("Invalid Arguments");
693                 return FALSE;
694         }
695
696         DBG("Application path = %s", path);
697         DBG("Call Id = %d", call_id);
698         DBG("Sender = %s", sender);
699
700         _bt_ag_agent_emit_signal(ag_dbus_conn, path,
701                                         BT_HEADSET_INTERFACE, "Reject",
702                                         g_variant_new("(u)", call_id));
703         FN_END;
704         return TRUE;
705 }
706
707 gboolean _bt_ag_agent_release_call(unsigned int call_id,
708                                 const gchar *path, const gchar *sender)
709 {
710         FN_START;
711
712         if (path == NULL || sender == NULL) {
713                 DBG("Invalid Arguments");
714                 return FALSE;
715         }
716
717         DBG("Application path = %s", path);
718         DBG("Call Id = %d", call_id);
719         DBG("Sender = %s", sender);
720
721         _bt_ag_agent_emit_signal(ag_dbus_conn, path,
722                                         BT_HEADSET_INTERFACE, "Release",
723                                         g_variant_new("(u)", call_id));
724
725         FN_END;
726         return TRUE;
727 }
728 /* LCOV_EXCL_STOP */
729
730 bt_hfp_agent_error_t _bt_ag_agent_dial_num(const gchar *number, guint flags)
731 {
732         bt_hfp_agent_error_t error_code = BT_HFP_AGENT_ERROR_NONE;
733         int callapp_type;
734         int phone_lock_state;
735         int condition;
736
737         FN_START;
738
739         if (number == NULL) {
740                 ERR("Invalid Argument");
741                 error_code = BT_HFP_AGENT_ERROR_INVALID_PARAM;
742                 goto fail;
743         }
744
745         DBG("Number = %s", number);
746         DBG("flags = %d", flags);
747
748         if (!__bt_is_phone_locked(&phone_lock_state)) {
749                 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
750                 goto fail;
751         }
752
753         if (!__bt_get_outgoing_callapp_type(&callapp_type)) {
754                 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
755                 goto fail;
756         }
757
758         if (!__bt_get_outgoing_call_condition(&condition)) {
759                 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
760                 goto fail;
761         }
762
763         if (condition == BT_MO_ONLY_UNLOCKED && phone_lock_state ==
764                 VCONFKEY_IDLE_LOCK) {
765                 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
766                 goto fail;
767         }
768
769         /* LCOV_EXCL_START */
770         if (callapp_type == BT_VIDEO_CALL) {
771                 if (!__bt_ag_agent_make_video_call(number)) {
772                         ERR("Problem launching application");
773                         error_code = BT_HFP_AGENT_ERROR_INTERNAL;
774                         goto fail;
775                 }
776         } else {
777                 if (!__bt_ag_agent_make_call(number)) {
778                         ERR("Problem launching application");
779                         error_code = BT_HFP_AGENT_ERROR_INTERNAL;
780                         goto fail;
781                 }
782         }
783         /* LCOV_EXCL_STOP */
784
785 fail:
786         FN_END;
787         return error_code;
788 }
789
790 bt_hfp_agent_error_t _bt_ag_agent_dial_memory(unsigned int location)
791 {
792         bt_hfp_agent_error_t error_code = BT_HFP_AGENT_ERROR_NONE;
793         char *number = NULL;
794         contacts_filter_h filter = NULL;
795         contacts_query_h query = NULL;
796         contacts_list_h list = NULL;
797         contacts_record_h record = NULL;
798         unsigned int projections[] = {
799                 _contacts_speeddial.number,
800         };
801
802         FN_START;
803
804         DBG("location = %d", location);
805
806         /*Get number from contacts location*/
807         if (contacts_connect() != CONTACTS_ERROR_NONE) {
808                 ERR(" contacts_connect failed");
809                 return BT_HFP_AGENT_ERROR_INTERNAL;
810         }
811
812         /* LCOV_EXCL_START */
813         contacts_filter_create(_contacts_speeddial._uri, &filter);
814
815         if (filter == NULL)
816                 goto done;
817
818         if (contacts_filter_add_int(filter,
819                 _contacts_speeddial.speeddial_number,
820                 CONTACTS_MATCH_EQUAL, location) !=
821                 CONTACTS_ERROR_NONE) {
822                 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
823                 goto done;
824         }
825
826         contacts_query_create(_contacts_speeddial._uri, &query);
827
828         if (query == NULL)
829                 goto done;
830
831         contacts_query_set_filter(query, filter);
832
833         if (contacts_query_set_projection(query, projections,
834                                 sizeof(projections)/sizeof(unsigned int)) !=
835                                 CONTACTS_ERROR_NONE) {
836                 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
837                 goto done;
838         }
839
840         if (contacts_db_get_records_with_query(query, 0, 1, &list) !=
841                                 CONTACTS_ERROR_NONE) {
842                 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
843                 goto done;
844         }
845
846         if (contacts_list_first(list) != CONTACTS_ERROR_NONE) {
847                 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
848                 goto done;
849         }
850
851         if (contacts_list_get_current_record_p(list, &record) !=
852                                 CONTACTS_ERROR_NONE) {
853                 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
854                 goto done;
855         }
856
857         if (record == NULL)
858                 goto done;
859
860         if (contacts_record_get_str(record, _contacts_speeddial.number, &number)
861                 != CONTACTS_ERROR_NONE) {
862                 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
863                 goto done;
864         }
865
866         if (number == NULL) {
867                 ERR("No number at the location");
868                 error_code = BT_HFP_AGENT_ERROR_INVALID_MEMORY_INDEX;
869                 goto done;
870         }
871
872         DBG("number %s", number);
873
874         /*Make Voice call*/
875         if (!__bt_ag_agent_make_call(number)) {
876                 ERR("Problem launching application");
877                 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
878         }
879
880         g_free(number);
881 done:
882         if (list != NULL)
883                 contacts_list_destroy(list, TRUE);
884
885         if (filter != NULL)
886                 contacts_filter_destroy(filter);
887
888         if (query != NULL)
889                 contacts_query_destroy(query);
890
891         contacts_disconnect();
892
893         FN_END;
894
895         return error_code;
896         /* LCOV_EXCL_STOP */
897 }
898
899 /* LCOV_EXCL_START */
900 bt_hfp_agent_error_t _bt_ag_agent_send_dtmf(const gchar *dtmf,
901                                 const gchar *path, const gchar *sender)
902 {
903         bt_hfp_agent_error_t ret;
904
905         FN_START;
906
907         if (dtmf == NULL || path == NULL || sender == NULL) {
908                 ERR("Invalid Argument");
909                 return BT_HFP_AGENT_ERROR_INVALID_PARAM;
910         }
911
912         DBG("Dtmf = %s", dtmf);
913         DBG("Application path = %s", path);
914         DBG("Sender = %s", sender);
915
916         ret = __bt_ag_agent_gdbus_method_send(sender,
917                                 path, TELEPHONY_APP_INTERFACE,
918                                 "SendDtmf", FALSE,
919                                 g_variant_new("(s)", dtmf));
920
921         return ret;
922 }
923
924 gboolean _bt_ag_agent_threeway_call(unsigned int chld_value,
925                                 const gchar *path, const gchar *sender)
926 {
927         FN_START;
928
929         if (path == NULL || sender == NULL) {
930                 DBG("Invalid Arguments");
931                 return FALSE;
932         }
933
934         DBG("Application path = %s", path);
935         DBG("Value = %d", chld_value);
936         DBG("Sender = %s", sender);
937
938 #if defined(TIZEN_PROFILE_WEARABLE) && defined(TIZEN_FEATURE_BT_HFP_AG)
939         /* Check if AG supports (i.e. ag_chld_str = "0,1,2") the requested CHLD;
940         if not return FALSE */
941         if (chld_value != 0 && chld_value != 1 && chld_value != 2)
942                 return FALSE;
943 #else
944         if (chld_value != 0 && chld_value != 1 && chld_value != 2 &&
945                                 chld_value != 3)
946                 return FALSE;
947 #endif
948         _bt_ag_agent_emit_signal(ag_dbus_conn, path,
949                                         BT_HEADSET_INTERFACE, "Threeway",
950                                         g_variant_new("(u)", chld_value));
951         FN_END;
952         return TRUE;
953 }
954 /* LCOV_EXCL_STOP */
955
956 bt_hfp_agent_error_t _bt_ag_agent_dial_last_num(void *device)
957 {
958         bt_hfp_agent_error_t err_code = BT_HFP_AGENT_ERROR_NONE;
959         char *last_num = NULL;
960         int type;
961         int callapp_type;
962         int phone_lock_state;
963         int condition;
964         contacts_list_h list = NULL;
965         contacts_query_h query = NULL;
966         contacts_filter_h filter = NULL;
967         contacts_record_h record = NULL;
968         unsigned int projections[] = {
969                 _contacts_phone_log.address,
970                 _contacts_phone_log.log_type,
971         };
972
973         FN_START;
974
975         if (contacts_connect() != CONTACTS_ERROR_NONE) {
976                 ERR(" contacts_connect failed");
977                 err_code = BT_HFP_AGENT_ERROR_INTERNAL;
978                 return err_code;
979         }
980
981         /* LCOV_EXCL_START */
982         contacts_filter_create(_contacts_phone_log._uri, &filter);
983
984         if (filter == NULL)
985                 goto done;
986
987         if (contacts_filter_add_int(filter, _contacts_phone_log.log_type,
988                                 CONTACTS_MATCH_EQUAL,
989                                 CONTACTS_PLOG_TYPE_VOICE_OUTGOING) !=
990                                 CONTACTS_ERROR_NONE) {
991                 ERR(" contacts_filter_add_int failed");
992                 err_code = BT_HFP_AGENT_ERROR_INTERNAL;
993                 goto done;
994         }
995
996         if (contacts_filter_add_operator(filter, CONTACTS_FILTER_OPERATOR_OR) !=
997                                 CONTACTS_ERROR_NONE) {
998                 ERR(" contacts_filter_add_operator failed");
999                 err_code = BT_HFP_AGENT_ERROR_INTERNAL;
1000                 goto done;
1001         }
1002
1003         if (contacts_filter_add_int(filter, _contacts_phone_log.log_type,
1004                                 CONTACTS_MATCH_EQUAL,
1005                                 CONTACTS_PLOG_TYPE_VIDEO_OUTGOING) !=
1006                                 CONTACTS_ERROR_NONE) {
1007                 ERR(" contacts_filter_add_int failed");
1008                 err_code = BT_HFP_AGENT_ERROR_INTERNAL;
1009                 goto done;
1010         }
1011
1012         contacts_query_create(_contacts_phone_log._uri, &query);
1013
1014         if (query == NULL)
1015                 goto done;
1016
1017         contacts_query_set_filter(query, filter);
1018
1019         if (contacts_query_set_projection(query, projections,
1020                                 sizeof(projections)/sizeof(unsigned int)) !=
1021                                 CONTACTS_ERROR_NONE) {
1022                 ERR(" contacts_query_set_projection failed");
1023                 err_code = BT_HFP_AGENT_ERROR_INTERNAL;
1024                 goto done;
1025         }
1026
1027         if (contacts_query_set_sort(query, _contacts_phone_log.log_time, false)
1028                 != CONTACTS_ERROR_NONE) {
1029                 ERR(" contacts_query_set_sort failed");
1030                 err_code = BT_HFP_AGENT_ERROR_INTERNAL;
1031                 goto done;
1032         }
1033
1034         if (contacts_db_get_records_with_query(query, 0, 1, &list)  !=
1035                                 CONTACTS_ERROR_NONE) {
1036                 ERR(" contacts_db_get_records_with_query failed");
1037                 err_code = BT_HFP_AGENT_ERROR_INTERNAL;
1038                 goto done;
1039         }
1040
1041         if (contacts_list_first(list)  != CONTACTS_ERROR_NONE) {
1042                 ERR(" contacts_list_first failed");
1043                 err_code = BT_HFP_AGENT_ERROR_INTERNAL;
1044                 goto done;
1045         }
1046
1047         if (contacts_list_get_current_record_p(list, &record)  !=
1048                                 CONTACTS_ERROR_NONE) {
1049                 err_code = BT_HFP_AGENT_ERROR_INTERNAL;
1050                 goto done;
1051         }
1052
1053         if (record == NULL)
1054                 goto done;
1055
1056         if (contacts_record_get_str(record, _contacts_phone_log.address,
1057                                 &last_num) != CONTACTS_ERROR_NONE) {
1058                 err_code = BT_HFP_AGENT_ERROR_INTERNAL;
1059                 goto done;
1060         }
1061
1062         if (last_num == NULL) {
1063                 ERR("No last number");
1064                 err_code = BT_HFP_AGENT_ERROR_NO_CALL_LOGS;
1065                 goto done;
1066         }
1067
1068         if (!__bt_is_phone_locked(&phone_lock_state)) {
1069                 err_code = BT_HFP_AGENT_ERROR_INTERNAL;
1070                 goto done;
1071         }
1072
1073         if (!__bt_get_outgoing_callapp_type(&callapp_type)) {
1074                 err_code = BT_HFP_AGENT_ERROR_INTERNAL;
1075                 goto done;
1076         }
1077
1078         if (!__bt_get_outgoing_call_condition(&condition)) {
1079                 ERR(" Failed to get the call condition");
1080                 err_code = BT_HFP_AGENT_ERROR_INTERNAL;
1081                 goto done;
1082         }
1083
1084         if (condition == BT_MO_ONLY_UNLOCKED &&
1085                 phone_lock_state == VCONFKEY_IDLE_LOCK) {
1086                 ERR(" call condition and phone lock state check fail");
1087                 err_code = BT_HFP_AGENT_ERROR_INTERNAL;
1088                 goto done;
1089         }
1090
1091         switch (callapp_type) {
1092         case BT_VOICE_CALL:
1093                 if (!__bt_ag_agent_make_call(last_num)) {
1094                         ERR("Problem launching application");
1095                         err_code = BT_HFP_AGENT_ERROR_INTERNAL;
1096                 }
1097                 break;
1098         case BT_VIDEO_CALL:
1099                 if (!__bt_ag_agent_make_video_call(last_num)) {
1100                         ERR("Problem launching application");
1101                         err_code = BT_HFP_AGENT_ERROR_INTERNAL;
1102                 }
1103                 break;
1104         case BT_FOLLOW_CALL_LOG:
1105                 if (contacts_record_get_int(record,
1106                         _contacts_phone_log.log_type,
1107                         &type) != CONTACTS_ERROR_NONE) {
1108                         err_code = BT_HFP_AGENT_ERROR_INTERNAL;
1109                         break;
1110                 }
1111                 if (type == CONTACTS_PLOG_TYPE_VOICE_OUTGOING) {
1112                         if (!__bt_ag_agent_make_call(last_num)) {
1113                                 ERR("Problem launching application");
1114                                 err_code = BT_HFP_AGENT_ERROR_INTERNAL;
1115                         }
1116                 } else if (type == CONTACTS_PLOG_TYPE_VIDEO_OUTGOING) {
1117                         if (!__bt_ag_agent_make_video_call(last_num)) {
1118                                 ERR("Problem launching application");
1119                                 err_code = BT_HFP_AGENT_ERROR_INTERNAL;
1120                         }
1121                 } else {
1122                                 err_code = BT_HFP_AGENT_ERROR_INTERNAL;
1123                 }
1124                 break;
1125         default:
1126                 err_code = BT_HFP_AGENT_ERROR_INTERNAL;
1127                 break;
1128         }
1129
1130 done:
1131
1132         if (list != NULL)
1133                 contacts_list_destroy(list, TRUE);
1134
1135         if (filter != NULL)
1136                 contacts_filter_destroy(filter);
1137
1138         if (query != NULL)
1139                 contacts_query_destroy(query);
1140
1141         contacts_disconnect();
1142
1143         if (last_num != NULL)
1144                 g_free(last_num);
1145
1146         FN_END;
1147
1148         return err_code;
1149         /* LCOV_EXCL_STOP */
1150 }
1151
1152 /* LCOV_EXCL_START */
1153 bt_hfp_agent_error_t _bt_ag_agent_vendor_cmd(const gchar *cmd,
1154                 const gchar *path, const gchar *sender)
1155 {
1156         bt_hfp_agent_error_t ret;
1157
1158         FN_START;
1159
1160         if (cmd == NULL || path == NULL || sender == NULL) {
1161                 ERR("Invalid Argument");
1162                 return BT_HFP_AGENT_ERROR_INVALID_PARAM;
1163         }
1164
1165         DBG("cmd = %s", cmd);
1166         DBG("Application path = %s", path);
1167         DBG("Sender = %s", sender);
1168
1169         ret = __bt_ag_agent_gdbus_method_send(sender,
1170                                 path, TELEPHONY_APP_INTERFACE,
1171                                 "VendorCmd", FALSE,
1172                                 g_variant_new("(s)", cmd));
1173         FN_END;
1174         return ret;
1175 }
1176 /* LCOV_EXCL_STOP */
1177
1178 gboolean _bt_ag_agent_get_signal_quality(void *device)
1179 {
1180         gint rssi;
1181
1182         FN_START;
1183
1184         if (vconf_get_int(VCONFKEY_TELEPHONY_RSSI, &rssi)) {
1185                 DBG("VCONFKEY_TELEPHONY_RSSI failed\n"); /* LCOV_EXCL_LINE */
1186                 goto fail;
1187         }
1188
1189         DBG("RSSI : %d", rssi);
1190
1191         _bt_hfp_signal_quality_reply(rssi, BT_SIGNAL_QUALITY_BER,
1192                 device);
1193
1194         FN_END;
1195         return TRUE;
1196 fail:
1197         /* LCOV_EXCL_START */
1198         FN_END;
1199         _bt_hfp_signal_quality_reply(-1, -1, device);
1200         return FALSE;
1201         /* LCOV_EXCL_STOP */
1202 }
1203
1204 gboolean _bt_ag_agent_get_battery_status(void *device)
1205 {
1206         gint battery_chrg_status;
1207         gint battery_capacity;
1208
1209         FN_START;
1210
1211         if (vconf_get_int(VCONFKEY_SYSMAN_BATTERY_CHARGE_NOW,
1212                                                 &battery_chrg_status)) {
1213                 DBG("VCONFKEY_SYSMAN_BATTERY_CHARGE_NOW failed\n"); /* LCOV_EXCL_LINE */
1214                 goto fail;
1215         }
1216
1217         DBG("Status : %d\n", battery_chrg_status);
1218
1219         if (vconf_get_int(VCONFKEY_SYSMAN_BATTERY_CAPACITY,
1220                                                 &battery_capacity)) {
1221                 DBG("VCONFKEY_SYSMAN_BATTERY_CAPACITY failed\n"); /* LCOV_EXCL_LINE */
1222                 goto fail;
1223         }
1224
1225         DBG("Capacity : %d\n", battery_capacity);
1226
1227         _bt_hfp_battery_property_reply(device,
1228                 battery_chrg_status, battery_capacity);
1229         FN_END;
1230         return TRUE;
1231
1232 fail:
1233         /* LCOV_EXCL_START */
1234         _bt_hfp_battery_property_reply(device, -1, -1);
1235         FN_END;
1236         return FALSE;
1237         /* LCOV_EXCL_STOP */
1238 }
1239
1240 gboolean _bt_ag_agent_get_operator_name(void *device)
1241 {
1242         char *operator_name;
1243         FN_START;
1244
1245         operator_name = vconf_get_str(VCONFKEY_TELEPHONY_NWNAME);
1246         if (NULL == operator_name) {
1247                 /* LCOV_EXCL_START */
1248                 DBG("vconf_get_str failed");
1249                 _bt_hfp_operator_reply(NULL, device);
1250                 return FALSE;
1251                 /* LCOV_EXCL_STOP */
1252         }
1253
1254         DBG("operator_name  = [%s]", operator_name);
1255
1256         _bt_hfp_operator_reply(operator_name, device);
1257
1258         free(operator_name);
1259
1260         FN_END;
1261         return TRUE;
1262 }
1263
1264 gboolean _bt_hfp_agent_nrec_status(gboolean status,
1265                         void *t_device)
1266 {
1267         FN_START;
1268         bt_ag_info_t *hs = (bt_ag_info_t *)t_device;
1269
1270         DBG("NREC status = %d", status);
1271         if (status)
1272                 hs->nrec_status = FALSE;
1273         else
1274                 hs->nrec_status = TRUE;
1275
1276         if (ag_dbus_conn)
1277                 _bt_ag_agent_emit_signal(ag_dbus_conn, hs->path,
1278                                         BT_HEADSET_INTERFACE, "NrecStatusChanged",
1279                                         g_variant_new("(b)", status));
1280         FN_END;
1281         return TRUE;
1282 }
1283
1284 gboolean _bt_ag_agent_get_imei_number(void *device)
1285 {
1286         FN_START;
1287         char *imei_number;
1288
1289         imei_number = tel_get_misc_me_imei_sync(tapi_handle);
1290         if (NULL == imei_number) {
1291                 ERR("tel_get_misc_me_imei_sync for imei_number failed");
1292                 goto fail;
1293         }
1294
1295         /* LCOV_EXCL_START */
1296         if (!g_utf8_validate(imei_number, -1, NULL)) {
1297                 free(imei_number);
1298                 ERR("get_imei_number : invalid UTF8");
1299                 goto fail;
1300         }
1301
1302         DBG_SECURE("imei_number  = [%s]", imei_number);
1303         _bt_hfp_get_imei_number_reply(imei_number, device);
1304         free(imei_number);
1305         FN_END;
1306         return TRUE;
1307         /* LCOV_EXCL_STOP */
1308 fail:
1309         _bt_hfp_get_imei_number_reply(NULL, device);
1310         FN_END;
1311         return FALSE;
1312 }
1313
1314 void _bt_ag_agent_get_manufacturer_name(void *device)
1315 {
1316         FN_START;
1317         char *manufacturer_name;
1318         int ret;
1319
1320         ret = system_info_get_platform_string("http://tizen.org/system/manufacturer",
1321                                                 &manufacturer_name);
1322         if (SYSTEM_INFO_ERROR_NONE != ret) {
1323                 /* LCOV_EXCL_START */
1324                 ERR("Get manufacturer_name failed : %d", ret);
1325                 if (NULL != manufacturer_name)
1326                         free(manufacturer_name);
1327
1328                 manufacturer_name = g_strdup("Unknown");
1329                 /* LCOV_EXCL_STOP */
1330         } else if (!g_utf8_validate(manufacturer_name, -1, NULL)) {
1331                 /* LCOV_EXCL_START */
1332                 free(manufacturer_name);
1333                 manufacturer_name = g_strdup("Unknown");
1334                 ERR("get_manufacturer_name : invalid UTF8");
1335                 /* LCOV_EXCL_STOP */
1336         }
1337
1338         DBG_SECURE("manufacturer_name  = [%s]", manufacturer_name);
1339         _bt_hfp_get_device_manufacturer_reply(manufacturer_name, device);
1340         free(manufacturer_name);
1341         FN_END;
1342 }
1343
1344 void _bt_ag_agent_get_imsi(void *device)
1345 {
1346         FN_START;
1347         TelSimImsiInfo_t imsi;
1348         memset(&imsi, 0, sizeof(TelSimImsiInfo_t));
1349         if (tel_get_sim_imsi(tapi_handle, &imsi) != TAPI_API_SUCCESS) {
1350                 ERR("tel_get_sim_imsi failed");
1351                 goto fail;
1352         }
1353         /* LCOV_EXCL_START */
1354         DBG_SECURE("tapi values %s %s %s", imsi.szMcc, imsi.szMnc, imsi.szMsin);
1355
1356         _bt_hfp_get_imsi_reply(imsi.szMcc, imsi.szMnc, imsi.szMsin, device);
1357         FN_END;
1358         return;
1359         /* LCOV_EXCL_STOP */
1360 fail:
1361         _bt_hfp_get_imsi_reply(NULL, NULL, NULL, device);
1362         FN_END;
1363 }
1364
1365 /* LCOV_EXCL_START */
1366 int _bt_ag_agent_registration_status_convert(int result)
1367 {
1368         switch (result) {
1369         case TAPI_NETWORK_SERVICE_LEVEL_NO:
1370                 return BT_AGENT_NETWORK_REG_STATUS_NOT_REGISTER;
1371         case TAPI_NETWORK_SERVICE_LEVEL_EMERGENCY:
1372                 return BT_AGENT_NETWORK_REG_STATUS_EMERGENCY;
1373         case TAPI_NETWORK_SERVICE_LEVEL_FULL:
1374                 return BT_AGENT_NETWORK_REG_STATUS_REGISTER_HOME_NETWORK;
1375         case TAPI_NETWORK_SERVICE_LEVEL_SEARCH:
1376                 return BT_AGENT_NETWORK_REG_STATUS_SEARCH;
1377         default:
1378                 return BT_AGENT_NETWORK_REG_STATUS_UNKNOWN;
1379         }
1380         return result;
1381 }
1382 /* LCOV_EXCL_STOP */
1383
1384 void _bt_ag_agent_get_creg_status(void *device)
1385 {
1386         FN_START;
1387         int result = 0;
1388         int ret = 0;
1389         int n = 1;
1390         int registration_status = 0;
1391         int roam_status = 0;
1392
1393         ret = tel_get_property_int(tapi_handle, TAPI_PROP_NETWORK_CIRCUIT_STATUS,
1394                                 &result);
1395         if (ret != TAPI_API_SUCCESS) {
1396                 ERR("tel_get_property_int failed");
1397                 return;
1398         }
1399         /* LCOV_EXCL_START */
1400         registration_status =
1401                         _bt_ag_agent_registration_status_convert(result);
1402
1403         DBG_SECURE("Registration status %d", result);
1404         DBG_SECURE("Mapped Status %d", registration_status);
1405         if (registration_status ==
1406                         BT_AGENT_NETWORK_REG_STATUS_REGISTER_HOME_NETWORK) {
1407                 ret = vconf_get_int(VCONFKEY_TELEPHONY_SVC_ROAM, &roam_status);
1408                 if (ret != 0) {
1409                         ERR("Get roaming status failed err = %d\n", ret);
1410                         return;
1411                 }
1412                 DBG_SECURE("Roam status %d", roam_status);
1413                 if (roam_status == 1) {
1414                         registration_status =
1415                                         BT_AGENT_NETWORK_REG_STATUS_REGISTERED_ROAMING;
1416                 }
1417         }
1418
1419         _bt_hfp_get_creg_status_reply(n, registration_status, device);
1420
1421         FN_END;
1422         return;
1423         /* LCOV_EXCL_STOP */
1424 }
1425
1426 void _bt_ag_agent_get_model_name(void *device)
1427 {
1428         FN_START;
1429         char *model_name;
1430         int ret;
1431
1432         ret = system_info_get_platform_string("http://tizen.org/system/model_name", &model_name);
1433         if (SYSTEM_INFO_ERROR_NONE != ret) {
1434                 ERR("Get model_name failed: %d", ret);
1435                 if (NULL != model_name)
1436                         free(model_name);
1437
1438                 model_name = g_strdup("Unknown");
1439         } else if (!g_utf8_validate(model_name, -1, NULL)) {
1440                 free(model_name);
1441                 model_name = g_strdup("Unknown");
1442                 ERR("get_model_name : invalid UTF8");
1443         }
1444
1445         DBG_SECURE("model_name  = [%s]", model_name);
1446         _bt_hfp_get_model_info_reply(model_name, device);
1447         free(model_name);
1448         FN_END;
1449 }
1450
1451 void _bt_ag_agent_get_revision_information(void *device)
1452 {
1453         FN_START;
1454         char *revision_info;
1455         int ret;
1456
1457         ret = system_info_get_platform_string("http://tizen.org/system/build.string",
1458                                 &revision_info);
1459         if (SYSTEM_INFO_ERROR_NONE != ret) {
1460                 ERR("Get revision_info failed: %d", ret);
1461                 if (NULL != revision_info)
1462                         free(revision_info);
1463
1464                 revision_info = g_strdup("Unknown");
1465         } else if (!g_utf8_validate(revision_info, -1, NULL)) {
1466                         free(revision_info);
1467                         revision_info = g_strdup("Unknown");
1468                         ERR("get_revision_info: invalid UTF8");
1469                 }
1470
1471         DBG_SECURE("revision_info  = [%s]", revision_info);
1472         _bt_hfp_get_revision_info_reply(revision_info, device);
1473         free(revision_info);
1474         FN_END;
1475 }
1476
1477 #if defined(TIZEN_PROFILE_WEARABLE) && defined(TIZEN_FEATURE_BT_HFP_AG)
1478 static gboolean __bt_ag_agent_launch_voice_dial(gboolean activate)
1479 {
1480         FN_START;
1481         bundle *b;
1482
1483         b = bundle_create();
1484         if (NULL == b) {
1485                 ERR("bundle_create() Failed");
1486                 return FALSE;
1487         }
1488
1489         bundle_add(b, "domain", "bt_headset");
1490         if (!activate)
1491                 bundle_add(b, "action_type", "deactivate");
1492
1493         aul_launch_app_async("org.tizen.svoice", b);
1494         bundle_free(b);
1495         FN_END;
1496         return TRUE;
1497 }
1498 #else
1499 static gboolean __bt_ag_agent_launch_voice_dial(gboolean activate)
1500 {
1501         FN_START;
1502         app_control_h service = NULL;
1503
1504         app_control_create(&service);
1505
1506         if (service == NULL) {
1507                 ERR("Service create failed");
1508                 return FALSE;
1509         }
1510
1511         app_control_set_app_id(service, "org.tizen.svoice");
1512         app_control_set_operation(service, APP_CONTROL_OPERATION_DEFAULT);
1513         if (app_control_add_extra_data(service, "domain", "bt_headset")
1514                                         != APP_CONTROL_ERROR_NONE) {
1515                 ERR("app_control_add_extra_data failed");
1516                 app_control_destroy(service);
1517                 return FALSE;
1518         }
1519
1520         if (!activate)
1521                 if (app_control_add_extra_data(service, "action_type", "deactivate")
1522                                         != APP_CONTROL_ERROR_NONE) {
1523                         ERR("app_control_add_extra_data failed");
1524                         app_control_destroy(service);
1525                         return FALSE;
1526                 }
1527
1528         if (app_control_send_launch_request(service, NULL, NULL) !=
1529                                                 APP_CONTROL_ERROR_NONE) {
1530                 ERR("launch failed");
1531                 app_control_destroy(service);
1532                 return FALSE;
1533         }
1534
1535         app_control_destroy(service);
1536         FN_END;
1537         return TRUE;
1538 }
1539 #endif
1540
1541 gboolean _bt_ag_agent_voice_dial(gboolean activate)
1542 {
1543         DBG("Activate = %d", activate);
1544
1545         return __bt_ag_agent_launch_voice_dial(activate);
1546 }
1547
1548 /* LCOV_EXCL_START */
1549 static void __bt_ag_codec_negotiation_info_reset(bt_ag_info_t *hs,
1550                                         gboolean reset)
1551 {
1552         hs->codec_info.is_negotiating = FALSE;
1553         hs->codec_info.requested_by_hf = FALSE;
1554         hs->codec_info.sending_codec = 0;
1555         if (reset) {
1556                 hs->codec_info.remote_codecs = 0;
1557                 hs->codec_info.final_codec = 0;
1558                 hs->nrec_status = FALSE;
1559         }
1560
1561         if (hs->codec_info.nego_timer) {
1562                 g_source_remove(hs->codec_info.nego_timer);
1563                 hs->codec_info.nego_timer = 0;
1564         }
1565         wbs_opts.wbs_enable = wbs_en;
1566 }
1567
1568 static gboolean __bt_ag_codec_negotiation_finished(gpointer user_data)
1569 {
1570         struct ag_codec *data = (struct ag_codec *)user_data;
1571
1572         if (g_strcmp0(data->codec_status, "finish") == 0) {
1573                 DBG("Codec negotiation finished");
1574                 __bt_ag_sco_connect(data->bt_ag_info);
1575                 __bt_ag_codec_negotiation_info_reset(data->bt_ag_info, FALSE);
1576                 g_free(data->codec_status);
1577                 g_free(data);
1578                 return TRUE;
1579         } else if (g_strcmp0(data->codec_status, "timeout") == 0) {
1580                 DBG("Timeout is occured in codec negotiation");
1581         }
1582
1583         if (data->bt_ag_info->codec_info.requested_by_hf) {
1584                 __bt_ag_codec_negotiation_info_reset(data->bt_ag_info, FALSE);
1585         } else {
1586                 __bt_ag_sco_connect(data->bt_ag_info);
1587                 __bt_ag_codec_negotiation_info_reset(data->bt_ag_info, FALSE);
1588         }
1589         g_free(data->codec_status);
1590         g_free(data);
1591
1592         return FALSE;
1593 }
1594
1595 static bt_hfp_agent_error_t __bt_ag_set_codec(void *device, char *method)
1596 {
1597         GDBusProxy *proxy;
1598         GVariant *ret;
1599         GError *err = NULL;
1600         bt_ag_info_t *bt_ag_info = (bt_ag_info_t *)device;
1601
1602         proxy =  g_dbus_proxy_new_sync(ag_dbus_conn,
1603                         G_DBUS_PROXY_FLAGS_NONE, NULL,
1604                         BLUEZ_SERVICE_NAME, DEFAULT_ADAPTER_OBJECT_PATH,
1605                         BT_ADAPTER_INTERFACE, NULL, &err);
1606
1607         if (!proxy) {
1608                 if (err) {
1609                         ERR("Unable to create proxy: %s", err->message);
1610                         g_clear_error(&err);
1611                 }
1612                 return BT_HFP_AGENT_ERROR_INTERNAL;
1613         }
1614
1615         ret = g_dbus_proxy_call_sync(proxy, method,
1616                         g_variant_new("(ss)", "Gateway", bt_ag_info->remote_addr),
1617                         G_DBUS_CALL_FLAGS_NONE, -1,
1618                         NULL, &err);
1619         if (ret == NULL) {
1620                 /* dBUS-RPC is failed */
1621                 ERR("dBUS-RPC is failed");
1622                 if (err != NULL) {
1623                         /* dBUS gives error cause */
1624                         ERR("D-Bus API failure: errCode[%x], message[%s]",
1625                                err->code, err->message);
1626
1627                         g_clear_error(&err);
1628                 }
1629                 return BT_HFP_AGENT_ERROR_INTERNAL;
1630         }
1631         g_variant_unref(ret);
1632
1633         return BT_HFP_AGENT_ERROR_NONE;
1634 }
1635
1636 static bt_hfp_agent_error_t __bt_ag_codec_selection_setup(bt_ag_info_t *hs,
1637                         uint32_t codec)
1638 {
1639         bt_hfp_agent_error_t err = BT_HFP_AGENT_ERROR_NONE;
1640
1641         DBG("Codec setup [%x]", codec);
1642
1643         /* 1. Compare sending codec & recieved code */
1644         if (hs->codec_info.sending_codec != codec)
1645                 err = BT_HFP_AGENT_ERROR_INTERNAL;
1646
1647         /* 2. Send WB or NB command */
1648         switch (codec) {
1649         case BT_CVSD_CODEC_ID:
1650                 err = __bt_ag_set_codec(hs, "SetNbParameters");
1651                 break;
1652         case BT_MSBC_CODEC_ID:
1653                 err = __bt_ag_set_codec(hs, "SetWbsParameters");
1654                 break;
1655         default:
1656                 err = BT_HFP_AGENT_ERROR_INTERNAL;
1657                 break;
1658         }
1659
1660         /* If the vendor specific calling returns error or codec is not correct,
1661          * we send CVSD Codec parameter to MM module. and also returns
1662          * normal value to HF
1663         */
1664         if (err != BT_HFP_AGENT_ERROR_NONE)
1665                 codec = BT_CVSD_CODEC_ID;
1666
1667         hs->codec_info.final_codec = codec;
1668
1669         return err;
1670 }
1671
1672 static bt_hfp_agent_error_t __bt_hfp_send_bcs_command(bt_ag_info_t *hs,
1673                         gboolean init_by_hf)
1674 {
1675         uint32_t codec;
1676         struct ag_codec *data = NULL;;
1677
1678         if (TIZEN_MODEL_NAME_TM1) {
1679                 codec = BT_CVSD_CODEC_ID;
1680         } else {
1681                 if (hs->codec_info.remote_codecs & BT_MSBC_CODEC_MASK)
1682                         codec = BT_MSBC_CODEC_ID;
1683                 else
1684                         codec = BT_CVSD_CODEC_ID;
1685         }
1686
1687         if (wbs_opts.wbs_enable == FALSE)
1688                 codec = BT_CVSD_CODEC_ID;
1689
1690         hs->codec = codec;
1691
1692         if (_bt_ag_send_at(hs, "\r\n+BCS: %d\r\n", codec) < 0)
1693                 return BT_HFP_AGENT_ERROR_INTERNAL;
1694         else
1695                 DBG("Send +BCS:%d\n", codec);
1696
1697         /* Send +BCS command to HF, and wait some times */
1698         hs->codec_info.is_negotiating = TRUE;
1699         hs->codec_info.sending_codec = codec;
1700         hs->codec_info.requested_by_hf = init_by_hf;
1701         hs->codec_info.final_codec = codec;
1702
1703         data = g_new0(struct ag_codec, 1);
1704         if (data == NULL)
1705                 return BT_HFP_AGENT_ERROR_NO_MEMORY;
1706
1707         data->bt_ag_info = hs;
1708         data->codec_status = g_strdup("timeout");
1709
1710         hs->codec_info.nego_timer = g_timeout_add_seconds(
1711                         HFP_CODEC_NEGOTIATION_TIMEOUT,
1712                         (GSourceFunc)__bt_ag_codec_negotiation_finished,
1713                         data);
1714
1715         return BT_HFP_AGENT_ERROR_NONE;
1716 }
1717
1718
1719 static bt_hfp_agent_error_t __bt_hfp_codec_connection_setup(
1720                                 bt_ag_info_t *hs, gboolean init_by_hf)
1721 {
1722         DBG("Request to codec connection by %s", init_by_hf ? "HF" : "AG");
1723
1724         if (hs->state < HEADSET_STATE_CONNECTED)
1725                 return BT_HFP_AGENT_ERROR_NOT_CONNECTED;
1726
1727         if (hs->codec_info.is_negotiating == TRUE) {
1728                 /* In codec negotiation, return and wait */
1729                 ERR("Codec nogotiation is in progress");
1730                 return BT_HFP_AGENT_ERROR_BUSY;
1731         }
1732
1733         /* Not support Codec Negotiation or Not recieved BAC command */
1734         if (!(ag.features & BT_AG_FEATURE_CODEC_NEGOTIATION) ||
1735                                 hs->codec_info.remote_codecs == 0) {
1736                 ERR("No support for Codec Negotiation or receive BAC command");
1737                 if (init_by_hf) {
1738                         return BT_HFP_AGENT_ERROR_INTERNAL;
1739                 } else {
1740                         __bt_ag_sco_connect(hs);
1741                         return BT_HFP_AGENT_ERROR_INTERNAL;
1742                 }
1743         }
1744
1745         /* If HF initiated codec connection setup, it should send OK command
1746          * before +BCS command transmission.
1747          */
1748         if (init_by_hf)
1749                 return HFP_STATE_MNGR_ERR_NONE;
1750         else
1751                 return __bt_hfp_send_bcs_command(hs, init_by_hf);
1752 }
1753
1754
1755 static int __hfp_parse_available_codecs(const char *cmd, uint32_t *codecs)
1756 {
1757         char *str = NULL;
1758         *codecs = 0x00000000;
1759
1760         str = strchr(cmd, '=');
1761         if (str == NULL)
1762                 return -EINVAL;
1763
1764         while (str != NULL) {
1765                 str++;
1766
1767                 if (atoi(str) == BT_CVSD_CODEC_ID)
1768                         *codecs |= BT_CVSD_CODEC_MASK;
1769                 else if (atoi(str) == BT_MSBC_CODEC_ID)
1770                         *codecs |= BT_MSBC_CODEC_MASK;
1771
1772                 str = strchr(str, ',');
1773         }
1774
1775         if (*codecs == 0x00000000)
1776                 return -EINVAL;
1777
1778         return 0;
1779 }
1780
1781 /* AT+BAC (Bluetooth Available Codecs) */
1782 static int __bt_hfp_available_codecs(bt_ag_info_t *hs, const char *buf)
1783 {
1784         uint32_t codecs = 0x00000000;
1785         hfp_state_manager_err_t err = HFP_STATE_MNGR_ERR_NONE;
1786
1787         if (!(ag.features & BT_AG_FEATURE_CODEC_NEGOTIATION)) {
1788                 err = HFP_STATE_MNGR_ERR_AG_FAILURE;
1789         } else if (__hfp_parse_available_codecs(buf, &codecs) < 0) {
1790                 err = HFP_STATE_MNGR_ERR_AG_FAILURE;
1791         } else {
1792                 DBG("Update remote available codecs [%x]", codecs);
1793                 hs->codec_info.remote_codecs = codecs;
1794         }
1795
1796         _bt_ag_send_response(hs, err);
1797
1798         /* Reset codec information and
1799          * restart codec connection setup by AG
1800          */
1801         hs->codec_info.final_codec = 0;
1802         if (hs->codec_info.nego_timer) {
1803                 hs->codec_info.is_negotiating = FALSE;
1804                 hs->codec_info.requested_by_hf = FALSE;
1805                 hs->codec_info.sending_codec = 0;
1806                 g_source_remove(hs->codec_info.nego_timer);
1807                 __bt_hfp_codec_connection_setup(hs, FALSE);
1808         }
1809
1810         return 0;
1811 }
1812
1813 /* AT+BCC (Bluetooth Codec Connection) */
1814 static int __bt_hfp_codec_connection(bt_ag_info_t *hs, const char *buf)
1815 {
1816         hfp_state_manager_err_t err = HFP_STATE_MNGR_ERR_NONE;
1817
1818         err = __bt_hfp_codec_connection_setup(hs, TRUE);
1819
1820         _bt_ag_send_response(hs, err);
1821
1822         if (err == HFP_STATE_MNGR_ERR_NONE)
1823                 err = __bt_hfp_send_bcs_command(hs, TRUE);
1824
1825         if (err != HFP_STATE_MNGR_ERR_NONE)
1826                 ERR("Fail to request codec connection setup");
1827
1828         return 0;
1829 }
1830
1831 /* AT+BCS (Bluetooth Codec Selection) */
1832 static int __bt_hfp_codec_selection(bt_ag_info_t *hs, const char *buf)
1833 {
1834         uint32_t codec = 0x00000000;
1835         hfp_state_manager_err_t err = HFP_STATE_MNGR_ERR_NONE;
1836         struct ag_codec *data = g_new0(struct ag_codec, 1);
1837
1838         /* Timer reset */
1839         if (hs->codec_info.nego_timer) {
1840                 g_source_remove(hs->codec_info.nego_timer);
1841                 hs->codec_info.nego_timer = 0;
1842         }
1843
1844         if (!(ag.features & BT_AG_FEATURE_CODEC_NEGOTIATION))
1845                 err = HFP_STATE_MNGR_ERR_AG_FAILURE;
1846         else if (__hfp_parse_available_codecs(buf, &codec) < 0)
1847                 err = HFP_STATE_MNGR_ERR_AG_FAILURE;
1848         else if (__bt_ag_codec_selection_setup(hs, codec) !=
1849                                         BT_HFP_AGENT_ERROR_NONE)
1850                 err = HFP_STATE_MNGR_ERR_AG_FAILURE;
1851
1852         data->bt_ag_info = hs;
1853         data->codec_status = g_strdup("finish");
1854         _bt_ag_send_response(hs, err);
1855         __bt_ag_codec_negotiation_finished(data);
1856
1857         return 0;
1858 }
1859
1860 static void __bt_ag_str2ba(const char *str, bt_addr *ba)
1861 {
1862         int i;
1863         for (i = 5; i >= 0; i--, str += 3)
1864                 ba->b[i] = strtol(str, NULL, 16);
1865 }
1866 /* LCOV_EXCL_STOP */
1867
1868 static const char *__bt_ag_state2str(hs_state_t state)
1869 {
1870         switch (state) {
1871         case HEADSET_STATE_DISCONNECTED:
1872                 return "disconnected";
1873         case HEADSET_STATE_CONNECTING:
1874                 return "connecting";
1875         case HEADSET_STATE_CONNECTED:
1876                 return "connected";
1877         case HEADSET_STATE_PLAY_IN_PROGRESS:
1878                 return "Play In Progress";
1879         case HEADSET_STATE_ON_CALL:
1880                 return "On Call";
1881         }
1882
1883         return NULL;
1884 }
1885
1886 void _bt_convert_addr_string_to_type_rev(unsigned char *addr,
1887                 const char *address)
1888 {
1889         int i;
1890         char *ptr = NULL;
1891
1892         ret_if(address == NULL);
1893         ret_if(addr == NULL);
1894
1895         for (i = 0; i < 6; i++) {
1896                 addr[5 - i] = strtol(address, &ptr, 16);
1897                 if (ptr[0] != '\0') {
1898                         if (ptr[0] != ':')
1899                                 return;
1900
1901                         address = ptr + 1;
1902                 }
1903         }
1904 }
1905
1906 /* LCOV_EXCL_START */
1907 static gboolean __bt_ag_check_nval(GIOChannel *chan)
1908 {
1909         struct pollfd file_desc;
1910
1911         memset(&file_desc, 0, sizeof(file_desc));
1912         file_desc.fd = g_io_channel_unix_get_fd(chan);
1913         file_desc.events = POLLNVAL;
1914
1915         if (poll(&file_desc, 1, 0) > 0 && (POLLNVAL & file_desc.revents))
1916                 return TRUE;
1917
1918         return FALSE;
1919 }
1920
1921 static int __bt_ag_sco_connect(bt_ag_info_t *hs)
1922 {
1923         struct sco_socket_addr sco_addr;
1924         int err;
1925         GIOChannel *io;
1926         int sco_skt;
1927         bt_voice bt_vo;
1928         bt_ag_slconn_t *slconn = hs->slc;
1929         /*guint watch_id;*/
1930
1931         if (hs->state == HEADSET_STATE_ON_CALL)
1932                 return BT_HFP_AGENT_ERROR_ALREADY_CONNECTED;
1933
1934         if (hs->state != HEADSET_STATE_CONNECTED)
1935                 return BT_HFP_AGENT_ERROR_NOT_CONNECTED;
1936 #ifdef TIZEN_FEATURE_BT_MEDIA_ENHANCE
1937         _bt_ag_agent_check_transport_state();
1938 #endif
1939
1940         /* Create Sco socket */
1941         sco_skt = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BT_SCO_PRTCL);
1942         if (sco_skt < 0) {
1943                 ERR("ERROR: Create socket failed.\n");
1944                 return BT_HFP_AGENT_ERROR_INTERNAL;
1945         }
1946
1947         /* Bind Sco Socket to Local BD addr */
1948         memset(&sco_addr, 0, sizeof(sco_addr));
1949         sco_addr.sco_family = AF_BLUETOOTH;
1950
1951         __bt_ag_str2ba(local_addr, &sco_addr.sco_bdaddr);
1952         DBG("Local BD address: %s", local_addr);
1953
1954         err = bind(sco_skt, (struct sockaddr *) &sco_addr, sizeof(sco_addr));
1955         if (err < 0) {
1956                 ERR("ERROR: sco socket binding failed");
1957                 ERR("Close SCO skt");
1958                 close(sco_skt);
1959                 return BT_HFP_AGENT_ERROR_INTERNAL;
1960         }
1961
1962         DBG("Socket FD : %d", sco_skt);
1963
1964         io = g_io_channel_unix_new(sco_skt);
1965         g_io_channel_set_close_on_unref(io, TRUE);
1966         /*g_io_channel_set_flags(io, G_IO_FLAG_NONBLOCK, NULL);
1967         g_io_channel_set_buffered(io, FALSE);
1968         g_io_channel_set_encoding(io, NULL, NULL);*/
1969
1970         if ((ag.features & BT_AG_FEATURE_CODEC_NEGOTIATION) &&
1971                 (slconn && (slconn->hs_features &
1972                         BT_HF_FEATURE_CODEC_NEGOTIATION)) &&
1973                         wbs_opts.wbs_enable == TRUE) {
1974                 bt_vo.setting = (hs->codec == BT_MSBC_CODEC_ID) ?
1975                                 BT_HFP_MSBC_VOICE : BT_HFP_CVSD_VOICE;
1976
1977                 DBG("set Bluetooth voice: %d", bt_vo.setting);
1978                 err = setsockopt(sco_skt, BT_SOCKET_LEVEL,
1979                                         BT_VOICE_NUM, &bt_vo, sizeof(bt_vo));
1980                 if (err < 0) {
1981                         ERR("ERROR: sco socket set socket option failed");
1982                         ERR("Close SCO skt");
1983                         g_io_channel_unref(io);
1984                         close(sco_skt);
1985                         return BT_HFP_AGENT_ERROR_INTERNAL;
1986                 }
1987         } else {
1988                 DBG("Set NB codec parameter");
1989                 __bt_ag_set_codec(hs, "SetNbParameters");
1990         }
1991
1992         memset(&sco_addr, 0, sizeof(sco_addr));
1993         sco_addr.sco_family = AF_BLUETOOTH;
1994         __bt_ag_str2ba(hs->remote_addr, &sco_addr.sco_bdaddr);
1995         DBG("remotel BD address: %s", hs->remote_addr);
1996
1997         err = connect(sco_skt, (struct sockaddr *) &sco_addr, sizeof(sco_addr));
1998         if (err < 0 && !(errno == EINPROGRESS || errno == EAGAIN)) {
1999                 ERR("ERROR: sco socket connect failed : %d", err);
2000                 ERR("Close SCO skt");
2001                 g_io_channel_unref(io);
2002                 close(sco_skt);
2003                 return BT_HFP_AGENT_ERROR_INTERNAL;
2004         }
2005
2006         /* Disabling the watch since SCO is connected */
2007         /*watch_id = __bt_ag_set_watch(io,
2008                         (GIOFunc) __bt_ag_sco_connect_cb, hs);
2009         if (watch_id)
2010                 DBG("SCO watch set Success");*/
2011
2012         hs->sco = io;
2013
2014         _bt_ag_set_headset_state(hs, HEADSET_STATE_ON_CALL);
2015         return BT_HFP_AGENT_ERROR_NONE;
2016 }
2017
2018 static void __bt_ag_close_sco(bt_ag_info_t *hs)
2019 {
2020         DBG("");
2021         if (hs->sco) {
2022                 int sock = g_io_channel_unix_get_fd(hs->sco);
2023                 shutdown(sock, SHUT_RDWR);
2024                 g_io_channel_unref(hs->sco);
2025                 hs->sco = NULL;
2026         }
2027
2028         if (hs->sco_id)
2029                 __bt_ag_agent_remove_watch(&hs->sco_id);
2030
2031         if (hs->sco_incoming_id)
2032                 __bt_ag_agent_remove_watch(&hs->sco_incoming_id);
2033 }
2034
2035 static gboolean __bt_ag_sco_server_conn_cb(GIOChannel *chan,
2036                                 GIOCondition cond, gpointer user_data)
2037 {
2038         bt_ag_info_t *ag_info = user_data;
2039
2040         DBG("");
2041         if (cond & G_IO_NVAL)
2042                 return FALSE;
2043
2044         if (cond & (G_IO_HUP | G_IO_ERR)) {
2045                 ag_info->sco = NULL;
2046                 if (ag_info->sco_id)
2047                         __bt_ag_agent_remove_watch(&ag_info->sco_id);
2048
2049                 if (ag_info->sco_incoming_id)
2050                         __bt_ag_agent_remove_watch(&ag_info->sco_incoming_id);
2051
2052                 if (ag_info->watch_id)
2053                         _bt_ag_set_headset_state(ag_info, HEADSET_STATE_CONNECTED);
2054                 return FALSE;
2055         }
2056         return TRUE;
2057 }
2058
2059 static gboolean __bt_ag_sco_server_cb(GIOChannel *chan,
2060                                 GIOCondition cond, gpointer user_data)
2061 {
2062         bt_ag_info_t *ag_info = user_data;
2063         int sco_skt;
2064         int cli_sco_sock;
2065         GIOChannel *sco_io;
2066         bt_ag_slconn_t *slconn = ag_info->slc;
2067         bt_voice bt_vo;
2068         int err;
2069
2070         if ((cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) ||
2071                                 __bt_ag_check_nval(chan)) {
2072                 ERR("cond or chan is not valid");
2073                 return FALSE;
2074         }
2075
2076         INFO_C("Incoming SCO....");
2077
2078         if (ag_info->state < HEADSET_STATE_CONNECTED)
2079                 return BT_HFP_AGENT_ERROR_NOT_CONNECTED;
2080
2081         sco_skt = g_io_channel_unix_get_fd(chan);
2082
2083         cli_sco_sock = accept(sco_skt, NULL, NULL);
2084         if (cli_sco_sock < 0) {
2085                 ERR("accept is failed");
2086                 return TRUE;
2087         }
2088
2089         sco_io = g_io_channel_unix_new(cli_sco_sock);
2090         g_io_channel_set_close_on_unref(sco_io, TRUE);
2091         g_io_channel_set_encoding(sco_io, NULL, NULL);
2092         g_io_channel_set_flags(sco_io, G_IO_FLAG_NONBLOCK, NULL);
2093         g_io_channel_set_buffered(sco_io, FALSE);
2094
2095         if ((ag.features & BT_AG_FEATURE_CODEC_NEGOTIATION) &&
2096                 (slconn && (slconn->hs_features &
2097                         BT_HF_FEATURE_CODEC_NEGOTIATION)) &&
2098                         wbs_opts.wbs_enable == TRUE) {
2099                 bt_vo.setting = (ag_info->codec == BT_MSBC_CODEC_ID) ?
2100                                 BT_HFP_MSBC_VOICE : BT_HFP_CVSD_VOICE;
2101
2102                 DBG("set Bluetooth voice: %d", bt_vo.setting);
2103                 err = setsockopt(cli_sco_sock, BT_SOCKET_LEVEL,
2104                                         BT_VOICE_NUM, &bt_vo, sizeof(bt_vo));
2105                 if (err < 0) {
2106                         ERR("Sco socket set socket option failed");
2107                         close(cli_sco_sock);
2108                         return FALSE;
2109                 }
2110         }
2111
2112         ag_info->sco = sco_io;
2113         ag_info->sco_incoming_id = g_io_add_watch(sco_io, G_IO_HUP | G_IO_ERR | G_IO_NVAL,
2114                                         __bt_ag_sco_server_conn_cb, ag_info);
2115
2116         if (remote_dev_path)
2117                 g_free(remote_dev_path);
2118
2119         remote_dev_path = g_strdup(ag_info->path);
2120
2121         _bt_ag_set_headset_state(ag_info, HEADSET_STATE_ON_CALL);
2122
2123         return TRUE;
2124 }
2125 /* LCOV_EXCL_STOP */
2126
2127 static int __bt_ag_start_sco_server(bt_ag_info_t *hs)
2128 {
2129         DBG("Start SCO server");
2130         struct sco_socket_addr addr;
2131         GIOChannel *sco_io;
2132         int sco_skt;
2133         bdaddr_t bd_addr = {{0},};
2134
2135         if (hs->sco_server_started) {
2136                 DBG("Already exsist");
2137                 return BT_HFP_AGENT_ERROR_ALREADY_EXSIST;
2138         }
2139
2140         /* Create socket */
2141         sco_skt = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BT_SCO_PRTCL);
2142         if (sco_skt < 0) {
2143                 ERR("Can't create socket:\n");
2144                 return BT_HFP_AGENT_ERROR_INTERNAL;
2145         }
2146
2147         /* Bind to local address */
2148         memset(&addr, 0, sizeof(addr));
2149         addr.sco_family = AF_BLUETOOTH;
2150
2151         _bt_convert_addr_string_to_type_rev(bd_addr.b, hs->remote_addr);
2152         DBG("Bind to address %s", hs->remote_addr);
2153         memcpy(&addr.sco_bdaddr, &bd_addr, sizeof(bdaddr_t));
2154
2155         if (bind(sco_skt, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
2156                 ERR("Can't bind socket:\n");
2157                 goto error;
2158         }
2159
2160         if (listen(sco_skt, 1)) {
2161                 ERR("Can not listen on the socket:\n");
2162                 goto error;
2163         }
2164
2165         sco_io = g_io_channel_unix_new(sco_skt);
2166         g_io_channel_set_close_on_unref(sco_io, TRUE);
2167         g_io_channel_set_encoding(sco_io, NULL, NULL);
2168         g_io_channel_set_flags(sco_io, G_IO_FLAG_NONBLOCK, NULL);
2169         g_io_channel_set_buffered(sco_io, FALSE);
2170
2171         hs->sco_server = sco_io;
2172         hs->sco_watch_id = g_io_add_watch(sco_io,
2173                         G_IO_IN | G_IO_HUP | G_IO_ERR |
2174                         G_IO_NVAL, __bt_ag_sco_server_cb, hs);
2175
2176         hs->sco_server_started = TRUE;
2177         return BT_HFP_AGENT_ERROR_NONE;
2178
2179 error:
2180         close(sco_skt);
2181         return BT_HFP_AGENT_ERROR_INTERNAL;
2182 }
2183
2184 /* LCOV_EXCL_START */
2185 void __bt_ag_stop_sco_server(bt_ag_info_t *hs)
2186 {
2187         DBG("Stop SCO server");
2188         if (hs->sco_server) {
2189                 g_io_channel_shutdown(hs->sco_server, TRUE, NULL);
2190                 g_io_channel_unref(hs->sco_server);
2191                 hs->sco_server = NULL;
2192         }
2193         hs->sco_server_started = FALSE;
2194 }
2195
2196 static int __bt_ag_headset_close_rfcomm(bt_ag_info_t *hs)
2197 {
2198         GIOChannel *rfcomm = hs->rfcomm;
2199
2200         if (rfcomm) {
2201                 g_io_channel_shutdown(rfcomm, TRUE, NULL);
2202                 g_io_channel_unref(rfcomm);
2203                 hs->rfcomm = NULL;
2204         }
2205
2206         g_free(hs->slc);
2207         hs->slc = NULL;
2208
2209         return 0;
2210 }
2211
2212 static gboolean __bt_ag_sco_cb(GIOChannel *chan, GIOCondition cond,
2213                         bt_ag_info_t *hs)
2214 {
2215         if (cond & G_IO_NVAL)
2216                 return FALSE;
2217
2218         if (name_owner_sig_id != -1)
2219                 g_dbus_connection_signal_unsubscribe(ag_dbus_conn,
2220                                         name_owner_sig_id);
2221         name_owner_sig_id = -1;
2222         g_free(sco_owner);
2223         sco_owner = NULL;
2224
2225         DBG("Audio connection disconnected");
2226         _bt_ag_set_headset_state(hs, HEADSET_STATE_CONNECTED);
2227
2228         return FALSE;
2229 }
2230
2231 void _bt_ag_set_headset_state(bt_ag_info_t *hs, hs_state_t state)
2232 {
2233         bt_ag_slconn_t *slconn = hs->slc;
2234         const char *hs_state;
2235         hs_state_t org_state = hs->state;
2236         gboolean val = FALSE;
2237
2238         if (org_state == state)
2239                 return;
2240
2241         hs_state = __bt_ag_state2str(state);
2242
2243         switch (state) {
2244         case HEADSET_STATE_CONNECTING:
2245                 _bt_ag_agent_emit_property_changed(ag_dbus_conn,
2246                                         hs->path,
2247                                         BT_HEADSET_INTERFACE, "State",
2248                                         g_variant_new("s", hs_state));
2249                 hs->state = state;
2250                 break;
2251
2252         case HEADSET_STATE_CONNECTED:
2253                 if (hs->state != HEADSET_STATE_PLAY_IN_PROGRESS)
2254                         _bt_ag_agent_emit_property_changed(ag_dbus_conn,
2255                                         hs->path,
2256                                         BT_HEADSET_INTERFACE, "State",
2257                                         g_variant_new("s", hs_state));
2258
2259                 if (hs->state < state) {
2260                         val = TRUE;
2261                         active_devices = g_slist_append(active_devices, hs);
2262                         _bt_ag_agent_emit_property_changed(ag_dbus_conn,
2263                                                 hs->path,
2264                                                 BT_HEADSET_INTERFACE,
2265                                                 "Connected",
2266                                                 g_variant_new("b", val));
2267
2268                         DBG("Device %s connected\n", hs->remote_addr);
2269 #if defined(TIZEN_SUPPORT_DUAL_HF)
2270                          if (!hs->is_companion_device)
2271                                 __bt_ag_start_sco_server(hs);
2272 #else
2273                         __bt_ag_start_sco_server(hs);
2274 #endif
2275
2276                         /* Set default code as Gateway NB */
2277                         __bt_ag_set_codec(hs, "SetNbParameters");
2278                 } else if (hs->state == HEADSET_STATE_ON_CALL) {
2279                         val = FALSE;
2280                         _bt_ag_agent_emit_property_changed(ag_dbus_conn,
2281                                                 hs->path,
2282                                                 BT_HEADSET_INTERFACE,
2283                                                 "Playing",
2284                                                 g_variant_new("b", val));
2285                 }
2286                 hs->state = state;
2287                 break;
2288
2289         case HEADSET_STATE_DISCONNECTED:
2290                 __bt_ag_close_sco(hs);
2291                 __bt_ag_headset_close_rfcomm(hs);
2292
2293                 if (hs->state == HEADSET_STATE_ON_CALL) {
2294                         val = FALSE;
2295                         _bt_ag_agent_emit_property_changed(ag_dbus_conn,
2296                                                 hs->path,
2297                                                 BT_HEADSET_INTERFACE,
2298                                                 "Playing",
2299                                                 g_variant_new("b", val));
2300                 }
2301
2302                 val = FALSE;
2303                 _bt_ag_agent_emit_property_changed(ag_dbus_conn,
2304                                 hs->path,
2305                                 BT_HEADSET_INTERFACE,
2306                                 "Connected",
2307                                 g_variant_new("b", val));
2308                 if (hs->state > HEADSET_STATE_CONNECTING)
2309                         _bt_hfp_device_disconnected(hs);
2310
2311                 active_devices = g_slist_remove(active_devices, hs);
2312
2313                 __bt_ag_codec_negotiation_info_reset(hs, TRUE);
2314 #if 0 /* SCO is crashed if below is called when SCO is opened by hf-agent */
2315                 __bt_ag_set_codec(hs, "SetNbParameters");
2316 #endif
2317                 hs->codec = 0;
2318
2319                 /* Since SCO server is binded on remote address */
2320                 /* Need to stop SCO server once heasdet disconencted*/
2321                 if (hs->sco_server_started)
2322                         __bt_ag_stop_sco_server(hs);
2323
2324                 g_free(hs->remote_addr);
2325                 g_free(hs);
2326                 break;
2327
2328         case HEADSET_STATE_PLAY_IN_PROGRESS:
2329         case HEADSET_STATE_ON_CALL:
2330                 val = TRUE;
2331                 _bt_ag_agent_emit_property_changed(ag_dbus_conn,
2332                                         hs->path,
2333                                         BT_HEADSET_INTERFACE, "State",
2334                                         g_variant_new("s", hs_state));
2335
2336                 /*add watch for sco data */
2337                 hs->sco_id = g_io_add_watch(hs->sco,
2338                                         G_IO_ERR | G_IO_NVAL,
2339                                         (GIOFunc) __bt_ag_sco_cb, hs);
2340
2341                 _bt_ag_agent_emit_property_changed(
2342                                 ag_dbus_conn, hs->path,
2343                                 BT_HEADSET_INTERFACE, "Playing",
2344                                 g_variant_new("b", val));
2345
2346                 if (slconn->microphone_gain >= 0)
2347                         _bt_ag_send_at(hs, "\r\n+VGM=%u\r\n",
2348                                 slconn->microphone_gain);
2349
2350                 if (slconn->speaker_gain >= 0)
2351                         _bt_ag_send_at(hs, "\r\n+VGS=%u\r\n",
2352                                 slconn->speaker_gain);
2353
2354                 hs->state = state;
2355                 break;
2356
2357         default:
2358                 hs->state = state;
2359                 break;
2360         }
2361
2362         INFO("STATE CHANGED from [%s(%d)] to [%s(%d)]",
2363                 __bt_ag_state2str(org_state), org_state, __bt_ag_state2str(state), state);
2364 }
2365 /* LCOV_EXCL_STOP */
2366
2367 static struct event at_event_callbacks[] = {
2368         { "AT+BRSF", _bt_hfp_supported_features },
2369         { "AT+CIND", _bt_hfp_report_indicators },
2370         { "AT+CMER", _bt_hfp_enable_indicators },
2371         { "AT+CHLD", _bt_hfp_call_hold },
2372         { "ATA", _bt_hfp_answer_call },
2373         { "ATD", _bt_hfp_dial_number },
2374         { "AT+VG", _bt_hfp_signal_gain_setting },
2375         { "AT+CHUP", _bt_hfp_terminate_call },
2376         { "AT+CKPD", _bt_hfp_key_press },
2377         { "AT+CLIP", _bt_hfp_cli_notification },
2378         { "AT+BTRH", _bt_hfp_response_and_hold },
2379         { "AT+BLDN", _bt_hfp_last_dialed_number },
2380         { "AT+VTS", _bt_hfp_dtmf_tone },
2381         { "AT+CNUM", _bt_hfp_subscriber_number },
2382         { "AT+CLCC", _bt_hfp_list_current_calls },
2383         { "AT+CMEE", _bt_hfp_extended_errors },
2384         { "AT+CCWA", _bt_hfp_call_waiting_notify },
2385         { "AT+COPS", _bt_hfp_operator_selection },
2386         { "AT+NREC", _bt_hfp_nr_and_ec },
2387         { "AT+BVRA", _bt_hfp_voice_dial },
2388         { "AT+XAPL", _bt_hfp_apl_command },
2389         { "AT+IPHONEACCEV", _bt_hfp_apl_command },
2390         { "AT+BIA", _bt_hfp_indicators_activation },
2391         { "AT+CPBS", _bt_hfp_select_pb_memory },
2392         { "AT+CPBR", _bt_hfp_read_pb_entries},
2393         { "AT+CPBF", _bt_hfp_find_pb_entires },
2394         { "AT+CSCS", _bt_hfp_select_character_set },
2395         { "AT+CSQ", _bt_hfp_get_signal_quality },
2396         { "AT+CBC", _bt_hfp_get_battery_charge_status },
2397         { "AT+CPAS", _bt_hfp_get_activity_status },
2398         { "AT+CGSN", _bt_hfp_get_equipment_identity },
2399         { "AT+CGMM", _bt_hfp_get_model_information },
2400         { "AT+CGMI", _bt_hfp_get_device_manufacturer },
2401         { "AT+CGMR", _bt_hfp_get_revision_information },
2402         { "AT+BAC", __bt_hfp_available_codecs },
2403         { "AT+BCC", __bt_hfp_codec_connection },
2404         { "AT+BCS", __bt_hfp_codec_selection },
2405         { "AT+XSAT", _bt_hfp_vendor_cmd },
2406         { "AT+CIMI", _bt_hfp_get_imsi },
2407         { "AT+CREG", _bt_hfp_get_creg_status },
2408         { 0 }
2409 };
2410
2411 int num_of_secure_command = 4;
2412 static const char* secure_command[] = {"CLCC", "CLIP", "CPBR", "CCWA"};
2413
2414 /* LCOV_EXCL_START */
2415 static void __bt_ag_agent_print_at_buffer(char *message, const char *buf)
2416 {
2417
2418         int i = 0;
2419         char s[MAX_BUFFER_SIZE] = {0, };
2420         gboolean hide = FALSE;
2421
2422         gboolean is_security_command = FALSE;
2423         char *xsat_ptr;
2424
2425         strncpy(s, buf, MAX_BUFFER_SIZE - 1);
2426
2427         for (i = 0; i < num_of_secure_command; i++) {
2428                 if (strstr(buf, secure_command[i])) {
2429                         is_security_command = TRUE;
2430                         break;
2431                 }
2432         }
2433
2434         /* +XSAT: 11,DISC */
2435         xsat_ptr =  strstr(s, "11,DISC,");
2436         if (xsat_ptr) {
2437                 xsat_ptr = xsat_ptr + 8;
2438                 int x = 0;
2439                 while (xsat_ptr[x] != '\0' && xsat_ptr[x] != '\r' && xsat_ptr[x] != '\n') {
2440                         xsat_ptr[x] = 'X';
2441                         x++;
2442                 }
2443         }
2444
2445         /* AT+XSAT=11,Q_CT,X,XXXX */
2446         xsat_ptr =  strstr(s, "11,Q_CT,");
2447         if (xsat_ptr) {
2448                 xsat_ptr = xsat_ptr + 8;
2449                 int x = 0;
2450                 while (xsat_ptr[x] != '\0' && xsat_ptr[x] != '\r' && xsat_ptr[x] != '\n') {
2451                         if (x > 1) /* ignore 0 and 1 position */
2452                                 xsat_ptr[x] = 'X';
2453                         x++;
2454                 }
2455         }
2456
2457         i = 0;
2458         while (s[i] != '\0') {
2459                 if (s[i] == '\r' || s[i] == '\n') {
2460                         s[i] = '.';
2461                 } else {
2462                         if (s[i] == '\"')
2463                                 hide = hide ? FALSE : TRUE;
2464                         else if (is_security_command && hide) {
2465                                 if (i % 2)
2466                                         s[i] = 'X';
2467                         }
2468                 }
2469                 i++;
2470         }
2471         if (message)
2472                 INFO("%s Buffer = [%s], Len(%zd)", message, s, strlen(s));
2473         else
2474                 INFO("[%s]", s);
2475 }
2476
2477 static int __bt_ag_at_handler(bt_ag_info_t *hs, const char *buf)
2478 {
2479         struct event *ev;
2480
2481         __bt_ag_agent_print_at_buffer("[AG AT CMD][RCVD] :", buf);
2482
2483         for (ev = at_event_callbacks; ev->cmd; ev++) {
2484                 if (!strncmp(buf, ev->cmd, strlen(ev->cmd)))
2485                         return ev->callback(hs, buf);
2486         }
2487
2488         return -EINVAL;
2489 }
2490 /* LCOV_EXCL_STOP */
2491
2492 static int __bt_ag_send_at_valist(bt_ag_info_t *hdset, va_list list,
2493                         char *list_format)
2494 {
2495         ssize_t final_written, count;
2496         char rsp_buffer[MAX_BUFFER_SIZE];
2497         int fd;
2498         int err;
2499
2500         count = vsnprintf(rsp_buffer, sizeof(rsp_buffer), list_format, list);
2501         if (count < 0) {
2502                 ERR("count is %zd", count);
2503                 return -EINVAL;
2504         }
2505
2506         if (!hdset->io_chan) {
2507                 ERR("__bt_ag_send_at_valist: headset not connected");
2508                 return -EIO;
2509         }
2510
2511         final_written = 0;
2512
2513         fd = g_io_channel_unix_get_fd(hdset->io_chan);
2514
2515         if (fd != 0) {
2516                 while (final_written < count) {
2517                         ssize_t written;
2518
2519                         do {
2520                                 written = write(fd, rsp_buffer + final_written,
2521                                                 count - final_written);
2522                         } while (written < 0 && errno == EINTR);
2523
2524                         if (written < 0) {
2525                                 err = -errno;
2526                                 ERR("write failed : %s (%d)", strerror(-err), -err);
2527                                 return -errno;
2528                         }
2529
2530                         final_written += written;
2531                 }
2532
2533                 /* Synchronize the sending buffer */
2534                 sync();
2535                 fsync(fd);
2536         } else {
2537                 ERR("FD is 0. remote_addr : %s", hdset->remote_addr);
2538                 return -1;
2539         }
2540
2541         __bt_ag_agent_print_at_buffer("[AG AT CMD][SENT]", rsp_buffer);
2542
2543         return 0;
2544 }
2545
2546 int __attribute__((format(printf, 2, 3)))
2547                         _bt_ag_send_at(bt_ag_info_t *hs, char *format, ...)
2548 {
2549         va_list ap;
2550         int ret;
2551
2552         va_start(ap, format);
2553         ret = __bt_ag_send_at_valist(hs, ap, format);
2554         va_end(ap);
2555
2556         return ret;
2557 }
2558
2559 void __attribute__((format(printf, 3, 4)))
2560                 _bt_ag_send_foreach_headset(GSList *devices,
2561                                 int (*cmp) (bt_ag_info_t *hs),
2562                                 char *format, ...)
2563 {
2564         GSList *l;
2565         va_list ap;
2566
2567         for (l = devices; l != NULL; l = l->next) {
2568                 bt_ag_info_t *hs = l->data;
2569                 int ret;
2570
2571                 if (cmp && cmp(hs) != 0)
2572                         continue;
2573
2574                 va_start(ap, format);
2575                 ret = __bt_ag_send_at_valist(hs, ap, format);
2576                 if (ret < 0)
2577                         ERR("Failed to send to headset: %s (%d)",
2578                                         strerror(-ret), -ret);
2579                 va_end(ap);
2580         }
2581 }
2582
2583 int _bt_ag_send_response(bt_ag_info_t *hs, hfp_state_manager_err_t err)
2584 {
2585         if ((err != HFP_STATE_MNGR_ERR_NONE) && hs->slc->is_cme_enabled)
2586                 return _bt_ag_send_at(hs, "\r\n+CME ERROR: %d\r\n", err);
2587
2588         switch (err) {
2589         case HFP_STATE_MNGR_ERR_NONE:
2590                 return _bt_ag_send_at(hs, "\r\nOK\r\n");
2591         case HFP_STATE_MNGR_ERR_NO_NETWORK_SERVICE:
2592                 return _bt_ag_send_at(hs, "\r\nNO CARRIER\r\n");
2593         default:
2594                 return _bt_ag_send_at(hs, "\r\nERROR\r\n");
2595         }
2596 }
2597
2598 /* LCOV_EXCL_START */
2599 static gboolean __bt_ag_event_handler(GIOChannel *channel,
2600                                 GIOCondition cond, void *user_data)
2601 {
2602         bt_ag_slconn_t *slconn;
2603         unsigned char event_buf[MAX_BUFFER_SIZE];
2604         ssize_t len;
2605         size_t available_buffer;
2606         int fd;
2607         bt_ag_info_t *bt_ag_info = (bt_ag_info_t *)user_data;
2608         int err_return = 0;
2609
2610
2611         if (cond & G_IO_NVAL)
2612                 return FALSE;
2613
2614         slconn = bt_ag_info->slc;
2615         if (cond & (G_IO_ERR | G_IO_HUP)) {
2616                 if (bt_ag_info->watch_id)
2617                         __bt_ag_agent_remove_watch(&bt_ag_info->watch_id);
2618
2619                 ERR("ERR or HUP on RFCOMM socket");
2620                 INFO_C("Disconnected [AG role] [Terminated by remote dev]");
2621                 goto failed;
2622         }
2623
2624         fd = g_io_channel_unix_get_fd(channel);
2625         len = read(fd, event_buf, sizeof(event_buf) - 1);
2626
2627         if (len < 0)
2628                 return FALSE;
2629         available_buffer = sizeof(slconn->buffer) - (slconn->start) -
2630                                 (slconn->length) - 1;
2631         if (available_buffer < (size_t) len) {
2632                 ERR("Buffer over flow");
2633                 goto failed;
2634         }
2635
2636         memcpy(&slconn->buffer[slconn->start + slconn->length], event_buf, len);
2637         slconn->length += len;
2638
2639         slconn->buffer[slconn->start + slconn->length] = '\0';
2640
2641         while (slconn->length > 0) {
2642                 char *get_cr;
2643                 int err;
2644                 off_t cmd_len;
2645
2646                 get_cr = strchr(&slconn->buffer[slconn->start], '\r');
2647                 if (!get_cr) {
2648                         ERR("Broken AT command received, break");
2649                         break;
2650                 }
2651
2652                 cmd_len = 1 + (off_t)(intptr_t)get_cr -
2653                         (off_t)(intptr_t)&slconn->buffer[slconn->start];
2654                 *get_cr = '\0';
2655
2656                 if (cmd_len > 1) {
2657                         DBG("Call AT handler");
2658                         err = __bt_ag_at_handler(bt_ag_info,
2659                                         &slconn->buffer[slconn->start]);
2660                 } else {
2661                         ERR("Failed to call AT handler");
2662                         err = 0;
2663                 }
2664
2665                 if (err < 0) {
2666                         switch (err) {
2667                         case -EINVAL:
2668                                 err_return = HFP_STATE_MNGR_ERR_NOT_SUPPORTED;
2669                                 break;
2670                         case -EACCES:
2671                                 err_return = HFP_STATE_MNGR_ERR_NOT_ALLOWED;
2672                                 break;
2673                         default:
2674                                 err_return = HFP_STATE_MNGR_ERR_NOT_SUPPORTED;
2675                                 break;
2676                         }
2677                         ERR("Error handling command %s: %s (%d)",
2678                                                 &slconn->buffer[slconn->start],
2679                                                 strerror(-err), -err);
2680                         err = _bt_ag_send_response(bt_ag_info,
2681                                         err_return);
2682                         if (err < 0)
2683                                 goto failed;
2684                 }
2685
2686                 slconn->start += cmd_len;
2687                 slconn->length -= cmd_len;
2688
2689                 if (slconn->length <= 0)
2690                         slconn->start = 0;
2691         }
2692         return TRUE;
2693 failed:
2694         ERR("Failed in event handler - SLC Disconnect");
2695         _bt_ag_set_headset_state(bt_ag_info,
2696                                         HEADSET_STATE_DISCONNECTED);
2697         return FALSE;
2698 }
2699
2700 static gboolean __bt_ag_agent_connection(gint32 fd, const gchar *device_path,
2701                                                 const gchar *object_path)
2702 {
2703         GIOFlags flags;
2704
2705         bt_ag_info_t *bt_ag_info = g_new0(bt_ag_info_t, 1);
2706         struct sockaddr_remote address;
2707         socklen_t address_len;
2708
2709         INFO_C("Connected [AG role]");
2710         bt_ag_info->rfcomm = NULL;
2711         bt_ag_info->slc = NULL;
2712         bt_ag_info->hfp_active = TRUE;
2713         bt_ag_info->vr_blacklisted = FALSE;
2714         bt_ag_info->state = HEADSET_STATE_DISCONNECTED;
2715         bt_ag_info->sco_server_started = FALSE;
2716         __bt_ag_codec_negotiation_info_reset(bt_ag_info, TRUE);
2717
2718         bt_ag_info->path = device_path;
2719         DBG("device_path = [%s]", device_path);
2720
2721         address_len = sizeof(address);
2722         if (getpeername(fd, (struct sockaddr *) &address, &address_len) != 0)
2723                 ERR("BD_ADDR is NULL");
2724
2725         DBG("RFCOMM connection for HFP/HSP is completed. Fd = [%d]", fd);
2726         bt_ag_info->fd = fd;
2727         bt_ag_info->io_chan = g_io_channel_unix_new(bt_ag_info->fd);
2728         flags = g_io_channel_get_flags(bt_ag_info->io_chan);
2729
2730         flags &= ~G_IO_FLAG_NONBLOCK;
2731         flags &= G_IO_FLAG_MASK;
2732         g_io_channel_set_flags(bt_ag_info->io_chan, flags, NULL);
2733         g_io_channel_set_encoding(bt_ag_info->io_chan, NULL, NULL);
2734         g_io_channel_set_buffered(bt_ag_info->io_chan, FALSE);
2735
2736         bt_ag_info->rfcomm = g_io_channel_ref(bt_ag_info->io_chan);
2737
2738         bt_ag_info->remote_addr = g_malloc0(BT_ADDRESS_STRING_SIZE);
2739         __bt_convert_addr_type_to_rev_string(bt_ag_info->remote_addr,
2740                                                 address.remote_bdaddr.b);
2741
2742 #if defined(TIZEN_SUPPORT_DUAL_HF)
2743         bt_ag_info->is_companion_device =
2744                         __bt_ag_agent_is_companion_device(bt_ag_info->remote_addr);
2745 #endif
2746
2747         DBG("remote Device Address = [%s]", bt_ag_info->remote_addr);
2748
2749         if (g_strcmp0(object_path, BT_HS_AG_AGENT_OBJECT_PATH) == 0) {
2750                 DBG("HSP connection completed");
2751                 _bt_ag_set_headset_state(bt_ag_info,
2752                                                 HEADSET_STATE_CONNECTED);
2753         } else {
2754                 DBG("HFP connection connecting");
2755                 _bt_ag_set_headset_state(bt_ag_info,
2756                                                 HEADSET_STATE_CONNECTING);
2757         }
2758
2759         __bt_ag_agent_start_watch(bt_ag_info);
2760
2761         bt_ag_info->slc = g_new0(bt_ag_slconn_t, 1);
2762         bt_ag_info->slc->speaker_gain = 15;
2763         bt_ag_info->slc->microphone_gain = 15;
2764         bt_ag_info->slc->is_nrec = TRUE;
2765
2766         return TRUE;
2767 }
2768
2769 static gboolean __bt_ag_agent_is_device_vr_blacklisted(const char *lap_addr)
2770 {
2771         char *buffer;
2772         FILE *fp;
2773         long size;
2774         size_t result;
2775         char *token;
2776         char *saveptr;
2777
2778         fp = fopen(AGENT_VR_BLACKLIST_FILE, "r");
2779
2780         if (fp == NULL) {
2781                 ERR("Unable to open VR blacklist file");
2782                 return FALSE;
2783         }
2784
2785         fseek(fp, 0, SEEK_END);
2786         size = ftell(fp);
2787         if (size <= 0) {
2788                 ERR("size is not a positive number");
2789                 fclose(fp);
2790                 return FALSE;
2791         }
2792
2793         rewind(fp);
2794
2795         buffer = g_malloc0(sizeof(char) * size);
2796         if (buffer == NULL) {
2797                 ERR("g_malloc0 is failed");
2798                 fclose(fp);
2799                 return FALSE;
2800         }
2801         result = fread((char *)buffer, 1, size, fp);
2802         fclose(fp);
2803         if (result != size) {
2804                 ERR("Read Error");
2805                 g_free(buffer);
2806                 return FALSE;
2807         }
2808
2809         token = strtok_r(buffer, "=", &saveptr);
2810         if (token == NULL) {
2811                 g_free(buffer);
2812                 return FALSE;
2813         }
2814
2815         while ((token = strtok_r(NULL, ",", &saveptr))) {
2816                 if (strlen(token) > 8)
2817                         token[8] = '\0';
2818                 if (0 == g_strcmp0(token, lap_addr)) {
2819                         INFO("Voice Recognition blacklisted");
2820                         g_free(buffer);
2821                         return TRUE;
2822                 }
2823         }
2824         g_free(buffer);
2825         return FALSE;
2826 }
2827
2828 static gboolean __bt_sco_open_delay_timeout_cb(gpointer user_data)
2829 {
2830         bt_ag_info_t *bt_ag_info = (bt_ag_info_t *)user_data;
2831         sco_open_timer_id = 0;
2832         DBG("sco_open_request (%d)", sco_open_request);
2833
2834         if (sco_open_request && bt_ag_info->state == HEADSET_STATE_CONNECTED) {
2835                 bt_ag_slconn_t *slconn = bt_ag_info->slc;
2836
2837                 INFO("try to open SCO");
2838                 sco_open_request = FALSE;
2839
2840                 if ((ag.features & BT_AG_FEATURE_CODEC_NEGOTIATION) &&
2841                                 (slconn && (slconn->hs_features &
2842                                         BT_HF_FEATURE_CODEC_NEGOTIATION))) {
2843                         switch (bt_ag_info->codec_info.final_codec) {
2844                         case BT_CVSD_CODEC_ID:
2845                                 __bt_ag_set_codec(bt_ag_info, "SetNbParameters");
2846                                 __bt_ag_sco_connect(bt_ag_info);
2847                                 break;
2848                         case BT_MSBC_CODEC_ID:
2849                                 __bt_ag_set_codec(bt_ag_info, "SetWbsParameters");
2850                                 __bt_ag_sco_connect(bt_ag_info);
2851                                 break;
2852                         default:
2853                                 __bt_hfp_codec_connection_setup(bt_ag_info, FALSE);
2854                                 break;
2855                         }
2856                 } else
2857                         __bt_ag_sco_connect(bt_ag_info);
2858         }
2859
2860         return FALSE;
2861 }
2862 /* LCOV_EXCL_STOP */
2863
2864 /*
2865 * Service level connection complete
2866 * indication and state management
2867 */
2868 void _bt_ag_slconn_complete(bt_ag_info_t *hs)
2869 {
2870         char lap_address[BT_LOWER_ADDRESS_LENGTH];
2871
2872         DBG("HFP Service Level Connection established\n");
2873
2874         /* Check device Voice Recognition blacklist status */
2875         g_strlcpy(lap_address, hs->remote_addr, sizeof(lap_address));
2876         hs->vr_blacklisted =
2877                 __bt_ag_agent_is_device_vr_blacklisted(lap_address);
2878
2879         if (sco_open_timer_id > 0) {
2880                 g_source_remove(sco_open_timer_id);
2881                 sco_open_timer_id = 0;
2882         }
2883
2884         sco_open_request = FALSE;
2885         sco_open_timer_id = g_timeout_add(BT_SCO_OPEN_DELAY_TIMER,
2886                                                 __bt_sco_open_delay_timeout_cb, hs);
2887
2888         _bt_ag_set_headset_state(hs, HEADSET_STATE_CONNECTED);
2889 }
2890
2891 /* LCOV_EXCL_START */
2892 static gboolean __bt_ag_agent_connection_release(bt_ag_info_t *hs)
2893 {
2894
2895         g_io_channel_shutdown(hs->io_chan, TRUE, NULL);
2896         g_io_channel_unref(hs->io_chan);
2897         hs->io_chan = NULL;
2898
2899         if (hs->sco) {
2900                 __bt_ag_close_sco(hs);
2901                 _bt_ag_set_headset_state(hs, HEADSET_STATE_CONNECTED);
2902         }
2903         __bt_ag_agent_remove_watch(&hs->watch_id);
2904
2905         _bt_ag_set_headset_state(hs, HEADSET_STATE_DISCONNECTED);
2906         return TRUE;
2907 }
2908
2909 static GQuark __bt_ag_agent_error_quark(void)
2910 {
2911         FN_START;
2912
2913         static GQuark quark = 0;
2914         if (!quark)
2915                 quark = g_quark_from_static_string("ag-agent");
2916
2917         FN_END;
2918         return quark;
2919 }
2920
2921 static GError *__bt_ag_agent_set_error(bt_hfp_agent_error_t error)
2922 {
2923         FN_START;
2924         ERR("error[%d]\n", error);
2925
2926         switch (error) {
2927         case BT_HFP_AGENT_ERROR_NOT_AVAILABLE:
2928                 return g_error_new(BT_AG_AGENT_ERROR, error,
2929                                         BT_ERROR_NOT_AVAILABLE);
2930         case BT_HFP_AGENT_ERROR_NOT_CONNECTED:
2931         return g_error_new(BT_AG_AGENT_ERROR, error,
2932                                         BT_ERROR_NOT_CONNECTED);
2933         case BT_HFP_AGENT_ERROR_BUSY:
2934                 return g_error_new(BT_AG_AGENT_ERROR, error,
2935                                                 BT_ERROR_BUSY);
2936         case BT_HFP_AGENT_ERROR_INVALID_PARAM:
2937                 return g_error_new(BT_AG_AGENT_ERROR, error,
2938                                                 BT_ERROR_INVALID_PARAM);
2939         case BT_HFP_AGENT_ERROR_ALREADY_EXSIST:
2940                 return g_error_new(BT_AG_AGENT_ERROR, error,
2941                                                 BT_ERROR_ALREADY_EXSIST);
2942         case BT_HFP_AGENT_ERROR_ALREADY_CONNECTED:
2943                 return g_error_new(BT_AG_AGENT_ERROR, error,
2944                                                 BT_ERROR_ALREADY_CONNECTED);
2945         case BT_HFP_AGENT_ERROR_NO_MEMORY:
2946                 return g_error_new(BT_AG_AGENT_ERROR, error,
2947                                                 BT_ERROR_NO_MEMORY);
2948         case BT_HFP_AGENT_ERROR_I_O_ERROR:
2949                 return g_error_new(BT_AG_AGENT_ERROR, error,
2950                                                 BT_ERROR_I_O_ERROR);
2951         case BT_HFP_AGENT_ERROR_OPERATION_NOT_AVAILABLE:
2952                 return g_error_new(BT_AG_AGENT_ERROR, error,
2953                                         BT_ERROR_OPERATION_NOT_AVAILABLE);
2954         case BT_HFP_AGENT_ERROR_BATTERY_STATUS:
2955                 return g_error_new(BT_AG_AGENT_ERROR, error,
2956                                         BT_ERROR_BATTERY);
2957         case BT_HFP_AGENT_ERROR_SIGNAL_STATUS:
2958                 return g_error_new(BT_AG_AGENT_ERROR, error,
2959                                         BT_ERROR_SIGNAL);
2960         case BT_HFP_AGENT_ERROR_NO_CALL_LOGS:
2961                 return g_error_new(BT_AG_AGENT_ERROR, error,
2962                                         BT_ERROR_NO_CALL_LOG);
2963         case BT_HFP_AGENT_ERROR_INTERNAL:
2964         default:
2965                 return g_error_new(BT_AG_AGENT_ERROR, error,
2966                                                 BT_ERROR_INTERNAL);
2967         }
2968         FN_END;
2969 }
2970
2971 static bt_ag_info_t *__bt_get_active_headset(const gchar *device_path)
2972 {
2973         GSList *l;
2974
2975         for (l = active_devices ; l; l = l->next) {
2976                 bt_ag_info_t *data = l->data;
2977                 if (device_path == NULL) /*just to avoid crash incase of "play" when dailed from device[NEEDS TO BE CHANGED]*/
2978                         return data;
2979                 if (g_strcmp0(data->path, device_path) == 0) {
2980                         INFO("Active device found");
2981                         return data;
2982                 }
2983         }
2984
2985         INFO("Active device not found");
2986         return NULL;
2987 }
2988
2989 static void __bt_ag_agent_method(GDBusConnection *connection,
2990                         const gchar *sender,
2991                         const gchar *object_path,
2992                         const gchar *interface_name,
2993                         const gchar *method_name,
2994                         GVariant *parameters,
2995                         GDBusMethodInvocation *invocation,
2996                         gpointer user_data)
2997 {
2998         FN_START;
2999
3000         INFO("method %s", method_name);
3001         INFO("object_path %s", object_path);
3002         int ret = BT_HFP_AGENT_ERROR_NONE;
3003         GError *err = NULL;
3004         const gchar *device_path = NULL;
3005
3006         if (g_strcmp0(method_name, "NewConnection") == 0) {
3007                 gint32 fd;
3008                 int index = 0;
3009                 GDBusMessage *msg;
3010                 GUnixFDList *fd_list;
3011                 GVariant *options = NULL;
3012                 int device_count = 0;
3013
3014                 device_count = g_slist_length(active_devices);
3015
3016                 INFO("device_count %d", device_count);
3017
3018                 if (device_count >= MAX_CONNECTED_DEVICES) {
3019                         ret = BT_HFP_AGENT_ERROR_INTERNAL;
3020                         goto fail;
3021                 }
3022
3023                 g_variant_get(parameters, "(oha{sv})",
3024                                                 &device_path, &index, &options);
3025
3026 #if defined(TIZEN_SUPPORT_DUAL_HF) && defined(TIZEN_PROFILE_WEARABLE)
3027                 /*
3028                  * Below code is not required for dual HF support for
3029                  * mobile devices
3030                  */
3031                 if (device_count &&
3032                         __bt_ag_agent_check_dual_hf_condition(device_path) == FALSE) {
3033                         INFO("not allow to connect 2nd HF connection");
3034                         ret = BT_HFP_AGENT_ERROR_INTERNAL;
3035                         goto fail;
3036                 }
3037 #endif
3038                 msg = g_dbus_method_invocation_get_message(invocation);
3039                 fd_list = g_dbus_message_get_unix_fd_list(msg);
3040                 if (fd_list == NULL) {
3041                         ret = BT_HFP_AGENT_ERROR_INTERNAL;
3042                         goto fail;
3043                 }
3044
3045                 fd = g_unix_fd_list_get(fd_list, index, NULL);
3046                 if (fd == -1) {
3047                         ret = BT_HFP_AGENT_ERROR_INTERNAL;
3048                         goto fail;
3049                 }
3050
3051                 DBG("FD is = [%d], device_path = [%s]\n", fd, device_path);
3052
3053                 if (!__bt_ag_agent_connection(fd, device_path, object_path)) {
3054                         ret = BT_HFP_AGENT_ERROR_INTERNAL;
3055                         goto fail;
3056                 }
3057
3058                 g_dbus_method_invocation_return_value(invocation, NULL);
3059         } else if (g_strcmp0(method_name, "RequestDisconnection") == 0) {
3060                 GSList *l;
3061
3062                 g_variant_get(parameters, "(o)", &device_path);
3063                 INFO("device_path %s", device_path);
3064
3065                 for (l = active_devices; l; l = l->next) {
3066                         bt_ag_info_t *data = l->data;
3067
3068                         INFO("data->path %s", data->path);
3069                         if (g_strcmp0(data->path, device_path) == 0) {
3070                                 if (!__bt_ag_agent_connection_release(data)) {
3071                                         ret = BT_HFP_AGENT_ERROR_INTERNAL;
3072                                         goto fail;
3073                                 }
3074                                 INFO_C("Disconnected [AG role] [Terminated by local host]");
3075                                 g_dbus_method_invocation_return_value(invocation, NULL);
3076                         }
3077                 }
3078         } else if (g_strcmp0(method_name, "RegisterApplication") == 0) {
3079                 gchar *path = NULL;
3080                 gchar *address = NULL;
3081                 g_variant_get(parameters, "(&s&s)", &path, &address);
3082                 /*local_addr = malloc(strlen(address));
3083                 memcpy(local_addr, address, strlen(address));*/
3084
3085                 DBG("Sender = %s, Application path = %s\n", sender, path);
3086                 ret = _bt_hfp_register_telephony_agent(TRUE, path, sender);
3087                 if (ret)
3088                         goto fail;
3089
3090                 g_free(local_addr);
3091                 local_addr = g_strdup(address);
3092                 DBG("Address = %s\n", local_addr);
3093                 g_dbus_method_invocation_return_value(invocation, NULL);
3094         } else if (g_strcmp0(method_name, "UnregisterApplication") == 0) {
3095                 gchar *path = NULL;
3096                 g_variant_get(parameters, "(&s)", &path);
3097
3098                 DBG("Application path = %s\n", path);
3099                 DBG("Sender = %s\n", sender);
3100
3101                 ret = _bt_hfp_register_telephony_agent(FALSE, path, sender);
3102                 if (ret)
3103                         goto fail;
3104
3105                 g_dbus_method_invocation_return_value(invocation, NULL);
3106         } else if (g_strcmp0(method_name, "IncomingCall") == 0) {
3107                 gchar *path = NULL;
3108                 gchar *number = NULL;
3109                 gint call_id = 0;
3110
3111                 g_variant_get(parameters, "(&s&si)", &path, &number, &call_id);
3112
3113                 DBG("Application path = %s", path);
3114                 DBG_SECURE("Phone number = %s", number);
3115                 DBG("Call id = %d", call_id);
3116
3117                 DBG("Sender = %s", sender);
3118
3119                 ret = _bt_hfp_incoming_call(path, number, call_id, sender);
3120                 if (ret)
3121                         goto fail;
3122                 g_dbus_method_invocation_return_value(invocation, NULL);
3123         } else if (g_strcmp0(method_name, "OutgoingCall") == 0) {
3124                 gchar *path = NULL;
3125                 gchar *number = NULL;
3126                 gint call_id = 0;
3127
3128                 g_variant_get(parameters, "(&s&si)", &path, &number, &call_id);
3129
3130                 DBG("Application path = %s", path);
3131                 DBG_SECURE("Phone number = %s", number);
3132                 DBG("Call id = %d", call_id);
3133
3134                 DBG("Sender = %s", sender);
3135
3136                 ret = _bt_hfp_outgoing_call(path, number, call_id, sender);
3137                 if (ret)
3138                         goto fail;
3139                 g_dbus_method_invocation_return_value(invocation, NULL);
3140         } else if (g_strcmp0(method_name, "ChangeCallStatus") == 0) {
3141                 gchar *path = NULL;
3142                 gchar *number = NULL;
3143                 gint status = 0;
3144                 gint call_id = 0;
3145                 GSList *l;
3146
3147                 g_variant_get(parameters, "(&s&sii)",
3148                                         &path, &number, &status, &call_id);
3149                 DBG("Application path = %s\n", path);
3150                 DBG_SECURE("Number = %s\n", number);
3151                 DBG("Status = %d\n", status);
3152                 DBG("Call id = %d\n", call_id);
3153                 DBG("Sender = %s\n", sender);
3154
3155                 ret = _bt_hfp_change_call_status(path,
3156                                         number, status, call_id, sender);
3157
3158                 if (_bt_hfp_is_call_exist() == FALSE) {
3159                         for (l = active_devices; l; l = l->next) {
3160                                 bt_ag_info_t *data = l->data;
3161
3162                                 if (data->state == HEADSET_STATE_ON_CALL) {
3163                                         __bt_ag_close_sco(data);
3164                                         _bt_ag_set_headset_state(data,
3165                                                 HEADSET_STATE_CONNECTED);
3166                                 }
3167                         }
3168                 }
3169
3170                 if (ret)
3171                         goto fail;
3172                 g_dbus_method_invocation_return_value(invocation, NULL);
3173         } else if (g_strcmp0(method_name, "GetProperties") == 0) {
3174                 GVariantBuilder *builder;
3175                 GVariant *var_data;
3176                 bt_ag_info_t *bt_ag_info = __bt_get_active_headset(remote_dev_path);
3177
3178                 if (bt_ag_info) {
3179                         gchar *codec = g_strdup("codec");
3180                         gchar *nrec = g_strdup("nrec");
3181
3182                         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
3183
3184                         g_variant_builder_add(builder, "{sv}",
3185                                         codec, g_variant_new("u", bt_ag_info->codec_info.final_codec));
3186                         g_variant_builder_add(builder, "{sv}",
3187                                         nrec, g_variant_new("b", bt_ag_info->nrec_status));
3188
3189                         var_data = g_variant_new("(a{sv})", builder);
3190                         g_variant_builder_unref(builder);
3191                         g_dbus_method_invocation_return_value(invocation, var_data);
3192
3193                         g_free(codec);
3194                         g_free(nrec);
3195                 } else {
3196                         ret = BT_HFP_AGENT_ERROR_NOT_CONNECTED;
3197                         goto fail;
3198                 }
3199         } else if (g_strcmp0(method_name, "Disconnect") == 0) {
3200                 char hdset_address[18] = { 0, };
3201                 GSList *l;
3202
3203                 for (l = active_devices; l; l = l->next) {
3204                         bt_ag_info_t *data = l->data;
3205
3206                         __bt_convert_addr_type_to_rev_string(hdset_address,
3207                                         (unsigned char *)data->remote_addr);
3208
3209                         DBG("Disconnect Headset %s, %s\n",
3210                                                 hdset_address, data->path);
3211                         _bt_ag_set_headset_state(data,
3212                                                 HEADSET_STATE_DISCONNECTED);
3213                 }
3214                 g_dbus_method_invocation_return_value(invocation, NULL);
3215         } else if (g_strcmp0(method_name, "IsConnected") == 0) {
3216                 gboolean is_connected = FALSE;
3217                 GSList *l;
3218
3219                 for (l = active_devices; l; l = l->next) {
3220                         bt_ag_info_t *data = l->data;
3221
3222                         if (data->state == HEADSET_STATE_CONNECTED)
3223                                 is_connected = TRUE;
3224                 }
3225                 DBG("is_connected : %s",
3226                                 is_connected ? "Connected" : "Disconnected");
3227
3228                 g_dbus_method_invocation_return_value(invocation,
3229                                 g_variant_new("(b)", is_connected));
3230         } else if (g_strcmp0(method_name, "IndicateCall") == 0) {
3231                 GSList *l;
3232
3233                 if (0 == g_slist_length(active_devices)) {
3234                         ret = BT_HFP_AGENT_ERROR_NOT_CONNECTED;
3235                         goto fail;
3236                 }
3237
3238                 if (ag.ring_timer) {
3239                         DBG("IndicateCall received when already indicating");
3240                         g_dbus_method_invocation_return_value(invocation, NULL);
3241                 }
3242
3243                 for (l = active_devices; l; l = l->next) {
3244                         bt_ag_info_t *data = l->data;
3245
3246                         if (data->state >= HEADSET_STATE_CONNECTED)
3247                                 _bt_ag_send_at(data, "\r\nRING\r\n");
3248                 }
3249
3250                 __bt_ring_timer_cb(NULL);
3251                 ag.ring_timer = g_timeout_add(AG_RING_INTERVAL,
3252                                 __bt_ring_timer_cb, NULL);
3253                 g_dbus_method_invocation_return_value(invocation, NULL);
3254         } else if (g_strcmp0(method_name, "CancelCall") == 0) {
3255                 if (0 == g_slist_length(active_devices)) {
3256                         ret = BT_HFP_AGENT_ERROR_NOT_CONNECTED;
3257                         goto fail;
3258                 }
3259
3260                 if (ag.ring_timer) {
3261                         g_source_remove(ag.ring_timer);
3262                         ag.ring_timer = 0;
3263                 } else
3264                         DBG("Got CancelCall method call but no call is active");
3265
3266                 g_dbus_method_invocation_return_value(invocation, NULL);
3267         } else if (g_strcmp0(method_name, "Play") == 0) {
3268                 bt_ag_info_t *bt_ag_info = __bt_get_active_headset(remote_dev_path);
3269                 bt_ag_slconn_t *slconn = NULL;
3270
3271                 if (bt_ag_info) {
3272                         slconn = bt_ag_info->slc;
3273                 } else {
3274                         ret = BT_HFP_AGENT_ERROR_NOT_CONNECTED;
3275                         goto fail;
3276                 }
3277
3278 #ifndef __TIZEN_OPEN__
3279 #ifdef MDM_PHASE_2
3280                 int mode;
3281                 if (slconn && FALSE == slconn->is_voice_recognition_running &&
3282                                 mdm_get_service() == MDM_RESULT_SUCCESS) {
3283                         mode = mdm_get_allow_bluetooth_outgoing_call();
3284                         mdm_release_service();
3285
3286                         if (mode == MDM_RESTRICTED) {
3287                                 ERR("[MDM] Not allow the outgoing call");
3288                                 ret = BT_HFP_AGENT_ERROR_OPERATION_NOT_AVAILABLE;
3289                                 goto fail;
3290                         }
3291                 }
3292 #endif
3293 #endif
3294
3295                 switch (bt_ag_info->state) {
3296                 case HEADSET_STATE_CONNECTING:
3297                 case HEADSET_STATE_DISCONNECTED:
3298                         ERR("HEADSET_STATE  ERROR");
3299                         ret = BT_HFP_AGENT_ERROR_NOT_CONNECTED;
3300                         break;
3301                 case HEADSET_STATE_CONNECTED:
3302                         break;
3303                 case HEADSET_STATE_PLAY_IN_PROGRESS:
3304                         ERR("Play In Progress");
3305                         ret = BT_HFP_AGENT_ERROR_BUSY;
3306                         break;
3307                 default:
3308                         break;
3309                 }
3310                 if (ret)
3311                         goto fail;
3312
3313                 if (sco_open_timer_id > 0) {
3314                         INFO("SCO open delay");
3315                         sco_open_request = TRUE;
3316                         g_dbus_method_invocation_return_value(invocation, NULL);
3317                         return;
3318                 }
3319
3320                 if ((ag.features & BT_AG_FEATURE_CODEC_NEGOTIATION) &&
3321                                 (slconn && (slconn->hs_features &
3322                                         BT_HF_FEATURE_CODEC_NEGOTIATION))) {
3323                         switch (bt_ag_info->codec_info.final_codec) {
3324                         case BT_CVSD_CODEC_ID:
3325                                 __bt_ag_set_codec(bt_ag_info, "SetNbParameters");
3326                                 ret = __bt_ag_sco_connect(bt_ag_info);
3327                                 break;
3328                         case BT_MSBC_CODEC_ID:
3329                                 __bt_ag_set_codec(bt_ag_info, "SetWbsParameters");
3330                                 ret = __bt_ag_sco_connect(bt_ag_info);
3331                                 break;
3332                         default:
3333                                 ret = __bt_hfp_codec_connection_setup(bt_ag_info, FALSE);
3334                                 break;
3335                         }
3336                 } else
3337                         ret = __bt_ag_sco_connect(bt_ag_info);
3338
3339                 if (ret)
3340                         goto fail;
3341
3342                 g_free(sco_owner);
3343                 sco_owner = g_strdup(sender);
3344
3345                 g_dbus_method_invocation_return_value(invocation, NULL);
3346
3347                 name_owner_sig_id = g_dbus_connection_signal_subscribe(ag_dbus_conn,
3348                                         NULL, NULL, "NameOwnerChanged", NULL, NULL, 0,
3349                                         __bt_ag_name_owner_changed_cb, NULL, NULL);
3350         } else if (g_strcmp0(method_name, "Stop") == 0) {
3351                 GSList *l;
3352
3353                 for (l = active_devices; l; l = l->next) {
3354                         bt_ag_info_t *data = l->data;
3355
3356                         if (data->state > HEADSET_STATE_CONNECTED) {
3357                                 __bt_ag_close_sco(data);
3358                                 _bt_ag_set_headset_state(data,
3359                                         HEADSET_STATE_CONNECTED);
3360                         }
3361                 }
3362
3363                 g_dbus_method_invocation_return_value(invocation, NULL);
3364         } else if (g_strcmp0(method_name, "IsPlaying") == 0) {
3365                 gboolean is_playing = FALSE;
3366                 GSList *l;
3367
3368                 for (l = active_devices; l; l = l->next) {
3369                         bt_ag_info_t *data = l->data;
3370
3371                         if (data->state == HEADSET_STATE_ON_CALL)
3372                                 is_playing = TRUE;
3373                 }
3374                 DBG("is_playing : %s", is_playing ? "Playing" : "Not Playing");
3375
3376                 g_dbus_method_invocation_return_value(invocation,
3377                                 g_variant_new("(b)", is_playing));
3378         } else if (g_strcmp0(method_name, "GetSpeakerGain") == 0) {
3379                 bt_ag_slconn_t *slconn = NULL;
3380                 guint16 gain_value = 0;
3381                 bt_ag_info_t *bt_ag_info = __bt_get_active_headset(remote_dev_path);
3382
3383                 if (bt_ag_info == NULL) {
3384                         ret = BT_HFP_AGENT_ERROR_NOT_AVAILABLE;
3385                         goto fail;
3386                 }
3387
3388                 if (bt_ag_info->state < HEADSET_STATE_CONNECTED) {
3389                         ret = BT_HFP_AGENT_ERROR_NOT_CONNECTED;
3390                         goto fail;
3391                 }
3392
3393                 slconn = bt_ag_info->slc;
3394                 if (slconn)
3395                         gain_value = (guint16) slconn->speaker_gain;
3396
3397                 g_dbus_method_invocation_return_value(invocation,
3398                                 g_variant_new("(q)", gain_value));
3399         } else if (g_strcmp0(method_name, "SetSpeakerGain") == 0) {
3400                 guint16 gain = 0;
3401                 bt_ag_info_t *bt_ag_info = __bt_get_active_headset(remote_dev_path);
3402
3403                 g_variant_get(parameters, "(q)", &gain);
3404                 DBG("Speaker gain = %d\n", gain);
3405
3406                 if (bt_ag_info == NULL) {
3407                         ret = BT_HFP_AGENT_ERROR_NOT_AVAILABLE;
3408                         goto fail;
3409                 }
3410
3411                 ret = _bt_hfp_set_speaker_gain(bt_ag_info, gain);
3412                 if (ret)
3413                         goto fail;
3414                 g_dbus_method_invocation_return_value(invocation, NULL);
3415         } else if (g_strcmp0(method_name, "GetMicrophoneGain") == 0) {
3416                 bt_ag_slconn_t *slconn = NULL;
3417                 guint16 gain_value = 0;
3418                 bt_ag_info_t *bt_ag_info = __bt_get_active_headset(remote_dev_path);
3419
3420                 if (bt_ag_info == NULL) {
3421                         ret = BT_HFP_AGENT_ERROR_NOT_AVAILABLE;
3422                         goto fail;
3423                 }
3424
3425                 if (bt_ag_info->state < HEADSET_STATE_CONNECTED) {
3426                         ret = BT_HFP_AGENT_ERROR_NOT_CONNECTED;
3427                         goto fail;
3428                 }
3429
3430                 slconn = bt_ag_info->slc;
3431                 if (slconn)
3432                         gain_value = (guint16) slconn->microphone_gain;
3433
3434                 g_dbus_method_invocation_return_value(invocation,
3435                                 g_variant_new("(q)", gain_value));
3436         } else if (g_strcmp0(method_name, "SetMicrophoneGain") == 0) {
3437                 guint16 gain = 0;
3438                 bt_ag_info_t *bt_ag_info = __bt_get_active_headset(remote_dev_path);
3439
3440                 g_variant_get(parameters, "(q)", &gain);
3441                 DBG("Microphone gain = %d\n", gain);
3442
3443                 if (bt_ag_info == NULL) {
3444                         ret = BT_HFP_AGENT_ERROR_NOT_AVAILABLE;
3445                         goto fail;
3446                 }
3447
3448                 ret = _bt_hfp_set_microphone_gain(bt_ag_info, gain);
3449                 if (ret)
3450                         goto fail;
3451                 g_dbus_method_invocation_return_value(invocation, NULL);
3452         } else if (g_strcmp0(method_name, "SetVoiceDial") == 0) {
3453                 bt_ag_info_t *bt_ag_info = __bt_get_active_headset(remote_dev_path);
3454                 if (bt_ag_info == NULL) {
3455                         ret = BT_HFP_AGENT_ERROR_NOT_AVAILABLE;
3456                         goto fail;
3457                 }
3458
3459                 bt_ag_slconn_t *slconn = bt_ag_info->slc;
3460                 gboolean enable;
3461
3462                 g_variant_get(parameters, "(b)", &enable);
3463                 DBG("VoiceDail enable = %d\n", enable);
3464
3465                 if ((slconn && !(slconn->hs_features &
3466                                         BT_HF_FEATURE_VOICE_RECOGNITION)))
3467                         ret = BT_HFP_AGENT_ERROR_INTERNAL;
3468                 else if (bt_ag_info->vr_blacklisted)
3469                         ret = BT_HFP_AGENT_ERROR_INTERNAL;
3470                 else
3471                         ret = _bt_hfp_set_voice_dial(bt_ag_info, enable);
3472
3473                 if (slconn)
3474                         slconn->is_voice_recognition_running = enable;
3475
3476                 if (ret)
3477                         goto fail;
3478                 g_dbus_method_invocation_return_value(invocation, NULL);
3479         } else if (g_strcmp0(method_name, "SendVendorAtCmd") == 0) {
3480                 gchar *cmd;
3481                 bt_ag_info_t *bt_ag_info = __bt_get_active_headset(remote_dev_path);
3482                 if (bt_ag_info == NULL) {
3483                         ret = BT_HFP_AGENT_ERROR_NOT_AVAILABLE;
3484                         goto fail;
3485                 }
3486
3487                 g_variant_get(parameters, "(&s)", &cmd);
3488                 if (cmd == NULL) {
3489                         ret = BT_HFP_AGENT_ERROR_INVALID_PARAM;
3490                         goto fail;
3491                 }
3492
3493                 DBG("vendor cmd = %s", cmd);
3494
3495                 ret = _bt_hfp_send_vendor_cmd(bt_ag_info, cmd);
3496                 if (ret)
3497                         goto fail;
3498                 g_dbus_method_invocation_return_value(invocation, NULL);
3499         } else if (g_strcmp0(method_name, "CheckPrivilege") == 0) {
3500                 DBG("Already pass dbus SMACK for bt-service::platform");
3501                 /* Return success */
3502                 g_dbus_method_invocation_return_value(invocation, NULL);
3503         }  else if (g_strcmp0(method_name, "SwapHeadset") == 0) {
3504                 GSList *l;
3505                 gchar *addr = NULL;
3506                 char address[BT_ADDRESS_STRING_SIZE];
3507                 char remote_addr[BT_ADDRESS_STRING_SIZE];
3508                 gboolean device_found = FALSE;
3509
3510                 g_variant_get(parameters, "(s)", &addr);
3511                 g_strlcpy(address, addr, sizeof(address));
3512                 DBG("Sender = %s", sender);
3513
3514                 /* Loop through connected headset list
3515                  * If found, update the remote_dev_path.
3516                  */
3517                 for (l = active_devices ; l; l = l->next) {
3518                         bt_ag_info_t *data = l->data;
3519                         g_strlcpy(remote_addr, data->remote_addr, sizeof(remote_addr));
3520                         if (g_strcmp0(remote_addr, address) == 0) {
3521                                 DBG("Active device found");
3522                                 if (data->path == NULL) {
3523                                         DBG("device path is null");
3524                                         ret = BT_HFP_AGENT_ERROR_INTERNAL;
3525                                         goto fail;
3526                                 }
3527                                 remote_dev_path = g_strdup(data->path);
3528                                 DBG("Setting device path %s as active device path", remote_dev_path);
3529                                 device_found = TRUE;
3530                                 break;
3531                         }
3532                 }
3533
3534                 if (!device_found) {
3535                         ret = BT_HFP_AGENT_ERROR_NOT_CONNECTED;
3536                         goto fail;
3537                 }
3538
3539                 g_dbus_method_invocation_return_value(invocation, NULL);
3540         }
3541
3542         INFO("-");
3543         return;
3544
3545 fail:
3546         err = __bt_ag_agent_set_error(ret);
3547         g_dbus_method_invocation_return_gerror(invocation, err);
3548         g_error_free(err);
3549         INFO("-");
3550 }
3551
3552 static const GDBusInterfaceVTable method_table = {
3553         __bt_ag_agent_method,
3554         NULL,
3555         NULL,
3556 };
3557
3558 static GDBusNodeInfo *__bt_ag_create_method_node_info
3559                                         (const gchar *introspection_data)
3560 {
3561         GError *err = NULL;
3562         GDBusNodeInfo *node_info = NULL;
3563
3564         if (introspection_data == NULL)
3565                 return NULL;
3566
3567         node_info = g_dbus_node_info_new_for_xml(introspection_data, &err);
3568
3569         if (err) {
3570                 ERR("Unable to create node: %s", err->message);
3571                 g_clear_error(&err);
3572         }
3573         return node_info;
3574 }
3575
3576 static GDBusConnection *__bt_ag_get_gdbus_connection(void)
3577 {
3578         FN_START;
3579
3580         GError *err = NULL;
3581
3582         if (ag_dbus_conn == NULL)
3583                 ag_dbus_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
3584
3585         if (!ag_dbus_conn) {
3586                 if (err) {
3587                         ERR("Unable to connect to dbus: %s", err->message);
3588                         g_clear_error(&err);
3589                 }
3590                 return NULL;
3591         }
3592         FN_END;
3593
3594         return ag_dbus_conn;
3595 }
3596
3597 static gboolean __bt_ag_register_profile_methods(void)
3598 {
3599         FN_START;
3600         GError *error = NULL;
3601         guint owner_id;
3602         GDBusNodeInfo *node_info = NULL;
3603         gchar *path;
3604
3605         owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
3606                                 BT_AG_SERVICE_NAME,
3607                                 G_BUS_NAME_OWNER_FLAGS_NONE,
3608                                 NULL, NULL, NULL,
3609                                 NULL, NULL);
3610
3611         DBG("owner_id is [%d]", owner_id);
3612
3613         node_info = __bt_ag_create_method_node_info(
3614                                 ag_agent_bluez_introspection_xml);
3615         if (node_info == NULL)
3616                 return FALSE;
3617
3618         path = g_strdup(BT_AG_AGENT_OBJECT_PATH);
3619         DBG("path is [%s]", path);
3620
3621         hf_bluez_id = g_dbus_connection_register_object(ag_dbus_conn, path,
3622                                         node_info->interfaces[0],
3623                                         &method_table,
3624                                         NULL, NULL, &error);
3625         if (hf_bluez_id == 0) {
3626                 ERR("Failed to register: %s", error->message);
3627                 g_error_free(error);
3628                 g_free(path);
3629                 g_dbus_node_info_unref(node_info);
3630                 return FALSE;
3631         }
3632         g_free(path);
3633
3634         /* Ag register profile methods for HSP*/
3635
3636         path = g_strdup(BT_HS_AG_AGENT_OBJECT_PATH);
3637         DBG("path is [%s]", path);
3638
3639         hs_bluez_id = g_dbus_connection_register_object(ag_dbus_conn, path,
3640                                         node_info->interfaces[0],
3641                                         &method_table,
3642                                         NULL, NULL, &error);
3643         if (hs_bluez_id == 0) {
3644                 ERR("Failed to register: %s", error->message);
3645                 g_error_free(error);
3646                 g_free(path);
3647                 g_dbus_node_info_unref(node_info);
3648                 return FALSE;
3649         }
3650         g_free(path);
3651         g_dbus_node_info_unref(node_info);
3652
3653         node_info = __bt_ag_create_method_node_info
3654                                 (ag_agent_app_introspection_xml);
3655         if (node_info == NULL)
3656                 return FALSE;
3657
3658         path = g_strdup(BT_AG_AGENT_OBJECT_PATH);
3659         DBG("path is [%s]", path);
3660
3661         app_id = g_dbus_connection_register_object(ag_dbus_conn, path,
3662                                                 node_info->interfaces[0],
3663                                                 &method_table,
3664                                                 NULL, NULL, &error);
3665         if (app_id == 0) {
3666                 ERR("Failed to register: %s", error->message);
3667                 g_error_free(error);
3668                 g_free(path);
3669                 g_dbus_node_info_unref(node_info);
3670                 return FALSE;
3671         }
3672         g_free(path);
3673         g_dbus_node_info_unref(node_info);
3674
3675         FN_END;
3676         return TRUE;
3677 }
3678
3679 static void __bt_ag_unregister_profile_methods(void)
3680 {
3681         DBG("");
3682
3683         if (hf_bluez_id > 0) {
3684                 g_dbus_connection_unregister_object(ag_dbus_conn,
3685                                                         hf_bluez_id);
3686                 hf_bluez_id = 0;
3687         }
3688
3689         if (hs_bluez_id > 0) {
3690                 g_dbus_connection_unregister_object(ag_dbus_conn,
3691                                                         hs_bluez_id);
3692                 hs_bluez_id = 0;
3693         }
3694
3695         if (app_id > 0) {
3696                 g_dbus_connection_unregister_object(ag_dbus_conn,
3697                                                         app_id);
3698                 app_id = 0;
3699         }
3700 }
3701
3702 static GDBusProxy *__bt_ag_gdbus_get_service_proxy(const gchar *service,
3703                                 const gchar *path, const gchar *interface)
3704 {
3705         return (service_gproxy) ? service_gproxy :
3706                         __bt_ag_gdbus_init_service_proxy(service,
3707                                         path, interface);
3708 }
3709
3710 static void __bt_ag_agent_register(gchar *path, uint16_t profile_version,
3711                                 char *profile_uuid, const char* profile_name)
3712 {
3713         FN_START;
3714         GDBusProxy *proxy;
3715         GVariant *ret;
3716         GError *error = NULL;
3717         GVariantBuilder *builder;
3718
3719         proxy = __bt_ag_gdbus_get_service_proxy(BLUEZ_SERVICE_NAME,
3720                 "/org/bluez", BLUEZ_PROFILE_MGMT_INTERFACE);
3721         if (proxy == NULL)
3722                 return;
3723
3724
3725         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
3726
3727         g_variant_builder_add(builder, "{sv}",
3728                         "Name", g_variant_new("s",
3729                         profile_name));
3730         g_variant_builder_add(builder, "{sv}",
3731                         "Version", g_variant_new("q", profile_version));
3732         /*g_variant_builder_add(builder, "{sv}",
3733                         "Role", g_variant_new("s","client"));*/
3734         if (g_strcmp0(path, BT_AG_AGENT_OBJECT_PATH) == 0) {
3735                 g_variant_builder_add(builder, "{sv}",
3736                                 "features", g_variant_new("q", ag.sdp_features));
3737         }
3738
3739         ret = g_dbus_proxy_call_sync(proxy, "RegisterProfile",
3740                                         g_variant_new("(osa{sv})", path,
3741                                                         profile_uuid, builder),
3742                                         G_DBUS_CALL_FLAGS_NONE, -1,
3743                                         NULL, &error);
3744         g_variant_builder_unref(builder);
3745         /* set the name and role for the profile*/
3746         if (ret == NULL) {
3747                 /* dBUS-RPC is failed */
3748                 ERR("dBUS-RPC is failed");
3749
3750                 if (error != NULL) {
3751                         /* dBUS gives error cause */
3752                         ERR("D-Bus API failure: errCode[%x], message[%s]",
3753                                         error->code, error->message);
3754
3755                         g_clear_error(&error);
3756                 }
3757                 g_free(path);
3758                 return;
3759         }
3760         g_variant_unref(ret);
3761         g_free(path);
3762
3763         FN_END;
3764         return;
3765 }
3766
3767 static void __bt_ag_agent_unregister(gchar *path)
3768 {
3769         FN_START;
3770         GDBusProxy *proxy;
3771         GVariant *ret;
3772         GError *error = NULL;
3773
3774         proxy = __bt_ag_gdbus_get_service_proxy(BLUEZ_SERVICE_NAME,
3775                 "/org/bluez", BLUEZ_PROFILE_MGMT_INTERFACE);
3776         if (proxy == NULL)
3777                 return;
3778
3779
3780         ret = g_dbus_proxy_call_sync(proxy, "UnregisterProfile",
3781                                         g_variant_new("(o)", path),
3782                                         G_DBUS_CALL_FLAGS_NONE, -1,
3783                                         NULL, &error);
3784         g_free(path);
3785         /* set the name and role for the profile*/
3786         if (ret == NULL) {
3787                 /* dBUS-RPC is failed */
3788                 ERR("dBUS-RPC is failed");
3789
3790                 if (error != NULL) {
3791                         /* dBUS gives error cause */
3792                         ERR("D-Bus API failure: errCode[%x], message[%s]",
3793                                         error->code, error->message);
3794
3795                         g_clear_error(&error);
3796                 }
3797                 return;
3798         }
3799         g_variant_unref(ret);
3800
3801         if (local_addr) {
3802                 g_free(local_addr);
3803                 local_addr = NULL;
3804         }
3805         FN_END;
3806         return;
3807 }
3808
3809 static void __bt_ag_agent_battery_status_cb(keynode_t *node)
3810 {
3811         int batt = vconf_keynode_get_int(node);
3812
3813         _bt_hfp_set_property_value("BatteryBarsChanged", batt);
3814 }
3815
3816 static void __bt_ag_agent_network_signal_status_cb(keynode_t *node)
3817 {
3818         int signal_bar = vconf_keynode_get_int(node);
3819
3820         BT_CHECK_SIGNAL_STRENGTH(signal_bar);
3821         _bt_hfp_set_property_value("SignalBarsChanged", signal_bar);
3822 }
3823
3824 static void __bt_ag_agent_lunar_connection_status_cb(keynode_t *node)
3825 {
3826         gboolean status = vconf_keynode_get_bool(node);
3827         GSList *l;
3828         DBG("status = %d", status);
3829
3830         if (status == TRUE) {
3831                 for (l = active_devices; l; l = l->next) {
3832                         bt_ag_info_t *data = l->data;
3833                         _bt_ag_send_at(data, "\r\n+BSIR:1\r\n");
3834                 }
3835         }
3836 }
3837
3838 static void __bt_ag_agent_network_register_status_cb(keynode_t *node)
3839 {
3840         int service = vconf_keynode_get_int(node);
3841         bt_hfp_agent_network_registration_status_t network_service;
3842         int roam_status;
3843         int ret;
3844
3845         DBG("Current Signal Level = [%d] \n", service);
3846
3847         switch (service) {
3848         case VCONFKEY_TELEPHONY_SVCTYPE_NONE:
3849         case VCONFKEY_TELEPHONY_SVCTYPE_NOSVC:
3850         case VCONFKEY_TELEPHONY_SVCTYPE_SEARCH:
3851                 service = 0;
3852                 break;
3853         default:
3854                 service = 1;
3855                 break;
3856         }
3857
3858         ret = vconf_get_int(VCONFKEY_TELEPHONY_SVC_ROAM, &roam_status);
3859         if (ret != 0) {
3860                 ERR("Get roaming status failed err = %d\n", ret);
3861                 return;
3862         }
3863
3864         if (roam_status == 0 && service == 1)
3865                 network_service = BT_AGENT_NETWORK_REG_STATUS_HOME;
3866         else if (roam_status == 1 && service == 1)
3867                 network_service = BT_AGENT_NETWORK_REG_STATUS_ROAMING;
3868         else
3869                 network_service = BT_AGENT_NETWORK_REG_STATUS_UNKOWN;
3870
3871         _bt_hfp_set_property_value("RegistrationChanged", network_service);
3872 }
3873
3874 static void __bt_ag_agent_subscribe_vconf_updates(void)
3875 {
3876         int ret;
3877
3878         DBG("\n");
3879
3880         ret = vconf_notify_key_changed(VCONFKEY_SYSMAN_BATTERY_CAPACITY,
3881                                 (void *)__bt_ag_agent_battery_status_cb, NULL);
3882         if (0 != ret)
3883                 ERR("Subsrciption to battery status failed err =  [%d]\n", ret);
3884
3885         ret = vconf_notify_key_changed(VCONFKEY_TELEPHONY_RSSI,
3886                         (void *)__bt_ag_agent_network_signal_status_cb, NULL);
3887         if (0 != ret)
3888                 ERR("Subsrciption to netowrk signal failed err =  [%d]\n", ret);
3889
3890         ret = vconf_notify_key_changed(VCONFKEY_TELEPHONY_SVCTYPE,
3891                         (void *)__bt_ag_agent_network_register_status_cb, NULL);
3892         if (0 != ret)
3893                 ERR("Subsrciption to network failed err =  [%d]\n", ret);
3894
3895         if (TIZEN_PROFILE_WEARABLE) {
3896                 ret = vconf_notify_key_changed(VCONF_KEY_BT_LUNAR_ENABLED,
3897                                 (void *)__bt_ag_agent_lunar_connection_status_cb, NULL);
3898                 if (0 != ret)
3899                         ERR("Subsrciption to lunar connection failed err =  [%d]\n", ret);
3900         }
3901 }
3902
3903 static void __bt_ag_agent_release_vconf_updates(void)
3904 {
3905         int ret;
3906
3907         DBG("\n");
3908
3909         ret = vconf_ignore_key_changed(VCONFKEY_SYSMAN_BATTERY_CAPACITY,
3910                         (vconf_callback_fn)__bt_ag_agent_battery_status_cb);
3911         if (0 != ret)
3912                 ERR("vconf_ignore_key_changed failed\n");
3913
3914         ret = vconf_ignore_key_changed(VCONFKEY_TELEPHONY_RSSI,
3915                 (vconf_callback_fn)__bt_ag_agent_network_signal_status_cb);
3916         if (0 != ret)
3917                 ERR("vconf_ignore_key_changed failed\n");
3918
3919         ret = vconf_ignore_key_changed(VCONFKEY_TELEPHONY_SVCTYPE,
3920                 (vconf_callback_fn)__bt_ag_agent_network_register_status_cb);
3921         if (0 != ret)
3922                 ERR("vconf_ignore_key_changed failed\n");
3923 }
3924
3925 static gboolean __bt_ag_agent_send_subscriber_number_changed(
3926                                                         const char *number)
3927 {
3928         const char *property = g_strdup("SubscriberNumberChanged");
3929
3930         FN_START;
3931
3932         DBG("Number is %s", number);
3933
3934         if (!_bt_hfp_set_property_name(property, number)) {
3935                 DBG("Error- set property for subscriber no change  - ERROR\n");
3936                 g_free((void *)property);
3937                 return FALSE;
3938         }
3939         g_free((void *)property);
3940         FN_END;
3941         return TRUE;
3942 }
3943 static void __bt_ag_agent_sigterm_handler(int signo)
3944 {
3945         int i;
3946         GSList *l;
3947
3948         ERR_C("***** Signal handler came with signal %d *****", signo);
3949
3950         for (l = active_devices ; l; l = l->next) {
3951                 bt_ag_info_t *data = l->data;
3952                 if (!__bt_ag_agent_connection_release(data))
3953                         ERR("__bt_ag_agent_connection_release failed");
3954         }
3955         if (ag_dbus_conn)
3956                 g_dbus_connection_flush(ag_dbus_conn, NULL, NULL, NULL);
3957
3958         if (gmain_loop) {
3959                 g_main_loop_quit(gmain_loop);
3960                 DBG("Exiting");
3961                 gmain_loop = NULL;
3962         } else {
3963                 INFO("Terminating AG agent");
3964                 exit(0);
3965         }
3966
3967         if (signo == SIGTERM)
3968                 return;
3969
3970         for (i = 0; i < BT_AG_SIG_NUM; i++)
3971                 sigaction(bt_ag_sig_to_handle[i], &(bt_ag_sigoldact[i]), NULL);
3972
3973         raise(signo);
3974 }
3975
3976 static void  __bt_ag_agent_tel_cb(TapiHandle *handle,
3977                                 int result,
3978                                 void *data,
3979                                 void *user_data)
3980 {
3981         TelSimMsisdnList_t *number;
3982         gchar *subscriber_number;
3983
3984         ERR("*********** result = %d", result);
3985
3986         if (result == TAPI_API_SIM_LOCKED ||
3987                 result == TAPI_API_SIM_NOT_INITIALIZED ||
3988                 result == TAPI_API_SERVICE_NOT_READY) {
3989                 DBG("initializing the tapi event for SIM status");
3990                 __bt_ag_agent_reg_sim_event(handle, user_data);
3991                 return;
3992         }
3993
3994         if (data == NULL)
3995                 return;
3996
3997         number = (TelSimMsisdnList_t *)data;
3998         subscriber_number = g_strdup(number->list[0].num);
3999         __bt_ag_agent_send_subscriber_number_changed(subscriber_number);
4000         g_free(subscriber_number);
4001 }
4002
4003 static void __bt_ag_agent_on_noti_sim_status(TapiHandle *handle,
4004                 const char *noti_id, void *data, void *user_data)
4005 {
4006         TelSimCardStatus_t *status = data;
4007         int tapi_result;
4008
4009         DBG("event TAPI_NOTI_SIM_STATUS received!! status[%d]", *status);
4010
4011         if (*status == TAPI_SIM_STATUS_SIM_INIT_COMPLETED) {
4012                 __bt_ag_agent_dereg_sim_event(handle);
4013                 tapi_result = tel_get_sim_msisdn(handle, __bt_ag_agent_tel_cb,
4014                                         user_data);
4015                 if (tapi_result != TAPI_API_SUCCESS)
4016                         ERR("Fail to get sim info: %d", tapi_result);
4017         }
4018 }
4019
4020 static void __bt_ag_agent_reg_sim_event(TapiHandle *handle, void *user_data)
4021 {
4022         int ret;
4023         ret = tel_register_noti_event(handle, TAPI_NOTI_SIM_STATUS,
4024                 __bt_ag_agent_on_noti_sim_status, user_data);
4025
4026         if (ret != TAPI_API_SUCCESS)
4027                 ERR("event register failed(%d)", ret);
4028 }
4029
4030 static void __bt_ag_agent_dereg_sim_event(TapiHandle *handle)
4031 {
4032         int ret;
4033         ret = tel_deregister_noti_event(handle, TAPI_NOTI_SIM_STATUS);
4034
4035         if (ret != TAPI_API_SUCCESS)
4036                 ERR("event deregister failed(%d)", ret);
4037 }
4038
4039 static void __bt_ag_name_owner_changed_cb(GDBusConnection *connection,
4040                                         const gchar *sender_name,
4041                                         const gchar *object_path,
4042                                         const gchar *interface_name,
4043                                         const gchar *signal_name,
4044                                         GVariant *parameters,
4045                                         gpointer user_data)
4046 {
4047         FN_START;
4048         char *name_owner = NULL;
4049         char *old_owner = NULL;
4050         char *new_owner = NULL;
4051
4052         if (strcasecmp(signal_name, "NameOwnerChanged") == 0) {
4053                 GSList *l;
4054
4055                 g_variant_get(parameters, "(sss)", &name_owner, &old_owner, &new_owner);
4056
4057                 _bt_hfp_release_all_calls_by_sender(name_owner);
4058
4059                 if (sco_owner == NULL)
4060                         return;
4061
4062                 if (strcasecmp(name_owner, sco_owner) == 0) {
4063                         if (name_owner_sig_id != -1)
4064                                 g_dbus_connection_signal_unsubscribe(ag_dbus_conn,
4065                                                         name_owner_sig_id);
4066                         name_owner_sig_id = -1;
4067                         g_free(sco_owner);
4068                         sco_owner = NULL;
4069
4070                         for (l = active_devices ; l; l = l->next) {
4071                                 bt_ag_info_t *data = l->data;
4072
4073                                 if (data->sco) {
4074                                         __bt_ag_close_sco(data);
4075                                         _bt_ag_set_headset_state(data,
4076                                                 HEADSET_STATE_CONNECTED);
4077                                 }
4078                         }
4079                 }
4080         }
4081 }
4082
4083 static void __bt_ag_agent_filter_cb(GDBusConnection *connection,
4084                                         const gchar *sender_name,
4085                                         const gchar *object_path,
4086                                         const gchar *interface_name,
4087                                         const gchar *signal_name,
4088                                         GVariant *parameters,
4089                                         gpointer user_data)
4090 {
4091         FN_START;
4092         char *path = NULL;
4093         GVariant *optional_param = NULL;
4094
4095         if (strcasecmp(signal_name, "InterfacesAdded") == 0) {
4096                 g_variant_get(parameters, "(&o@a{sa{sv}})", &path, &optional_param);
4097                 if (!path) {
4098                         if (optional_param)
4099                                 g_variant_unref(optional_param);
4100                         ERR("Invalid adapter path");
4101                         return;
4102                 }
4103
4104                 INFO("Adapter Path = [%s]", path);
4105                 if (strcasecmp(path, DEFAULT_ADAPTER_OBJECT_PATH) == 0) {
4106                         gchar *obj_path = g_strdup(BT_AG_AGENT_OBJECT_PATH);
4107                         __bt_ag_agent_register(obj_path, hfp_ver,
4108                                  HFP_AG_UUID, "Hands-Free Audio Gateway");
4109
4110                         obj_path =  g_strdup(BT_HS_AG_AGENT_OBJECT_PATH);
4111                         __bt_ag_agent_register(obj_path, hsp_ver,
4112                                 HSP_AG_UUID, "Headset Audio Gateway");
4113                 }
4114         } else if (strcasecmp(signal_name, "InterfacesRemoved") == 0) {
4115                 g_variant_get(parameters, "(&o@as)", &path, &optional_param);
4116                 if (!path) {
4117                         if (optional_param)
4118                                 g_variant_unref(optional_param);
4119                         ERR("Invalid adapter path");
4120                         return;
4121                 }
4122
4123                 INFO("Adapter Path = [%s]", path);
4124                 if (strcasecmp(path, DEFAULT_ADAPTER_OBJECT_PATH) == 0) {
4125                         gchar *obj_path = g_strdup(BT_AG_AGENT_OBJECT_PATH);
4126                         __bt_ag_agent_unregister(obj_path);
4127
4128                         obj_path =  g_strdup(BT_HS_AG_AGENT_OBJECT_PATH);
4129                         __bt_ag_agent_unregister(obj_path);
4130                 }
4131         }
4132
4133         if (optional_param)
4134                 g_variant_unref(optional_param);
4135
4136         FN_END;
4137 }
4138
4139 static void __bt_ag_agent_dbus_deinit(void)
4140 {
4141
4142         if (service_gproxy) {
4143                 g_object_unref(service_gproxy);
4144                 service_gproxy = NULL;
4145         }
4146
4147         if (app_gproxy) {
4148                 g_object_unref(app_gproxy);
4149                 app_gproxy = NULL;
4150         }
4151
4152         if (ag_dbus_conn) {
4153                 __bt_ag_unregister_profile_methods();
4154
4155                 if (interface_added_sig_id)
4156                         g_dbus_connection_signal_unsubscribe(ag_dbus_conn,
4157                                                 interface_added_sig_id);
4158
4159                 if (interface_removed_sig_id)
4160                         g_dbus_connection_signal_unsubscribe(ag_dbus_conn,
4161                                                 interface_removed_sig_id);
4162
4163                 if (name_owner_sig_id)
4164                         g_dbus_connection_signal_unsubscribe(ag_dbus_conn,
4165                                                 name_owner_sig_id);
4166 #ifdef TIZEN_FEATURE_BT_MEDIA_ENHANCE
4167                 if (media_sig_id)
4168                         g_dbus_connection_signal_unsubscribe(ag_dbus_conn,
4169                                                 media_sig_id);
4170                 media_sig_id = 0;
4171
4172                 if (media_state_sig_id)
4173                         g_dbus_connection_signal_unsubscribe(ag_dbus_conn,
4174                                                 media_state_sig_id);
4175                 media_state_sig_id = 0;
4176 #endif
4177
4178                 interface_added_sig_id = 0;
4179                 interface_removed_sig_id = 0;
4180                 name_owner_sig_id = 0;
4181                 g_free(sco_owner);
4182                 sco_owner = NULL;
4183
4184                 g_object_unref(ag_dbus_conn);
4185                 ag_dbus_conn = NULL;
4186         }
4187         return;
4188 }
4189
4190 static int __bt_ag_agent_get_adapter_path(GDBusConnection *conn, char *path)
4191 {
4192         GError *err = NULL;
4193         GDBusProxy *manager_proxy = NULL;
4194         GVariant *result = NULL;
4195         char *adapter_path = NULL;
4196
4197         if (conn == NULL)
4198                 return BT_HFP_AGENT_ERROR_INTERNAL;
4199
4200         manager_proxy =  g_dbus_proxy_new_sync(conn,
4201                         G_DBUS_PROXY_FLAGS_NONE, NULL,
4202                         BLUEZ_SERVICE_NAME,
4203                         "/",
4204                         BT_MANAGER_INTERFACE,
4205                         NULL, &err);
4206
4207         if (!manager_proxy) {
4208                 ERR("Unable to create proxy: %s", err->message);
4209                 goto fail;
4210         }
4211
4212         result = g_dbus_proxy_call_sync(manager_proxy, "DefaultAdapter", NULL,
4213                         G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
4214         if (!result) {
4215                 if (err != NULL)
4216                         ERR("Fail to get DefaultAdapter (Error: %s)", err->message);
4217                 else
4218                         ERR("Fail to get DefaultAdapter");
4219
4220                 goto fail;
4221         }
4222
4223         if (g_strcmp0(g_variant_get_type_string(result), "(o)")) {
4224                 ERR("Incorrect result\n");
4225                 goto fail;
4226         }
4227
4228         g_variant_get(result, "(&o)", &adapter_path);
4229
4230         if (adapter_path == NULL ||
4231                 strlen(adapter_path) >= BT_ADAPTER_OBJECT_PATH_MAX) {
4232                 ERR("Adapter path is inproper\n");
4233                 goto fail;
4234         }
4235
4236         if (path)
4237                 g_strlcpy(path, adapter_path, BT_ADAPTER_OBJECT_PATH_MAX);
4238
4239         g_variant_unref(result);
4240         g_object_unref(manager_proxy);
4241
4242         return 0;
4243
4244 fail:
4245         g_clear_error(&err);
4246
4247         if (result)
4248                 g_variant_unref(result);
4249
4250         if (manager_proxy)
4251                 g_object_unref(manager_proxy);
4252
4253         return BT_HFP_AGENT_ERROR_INTERNAL;
4254
4255 }
4256 /* LCOV_EXCL_STOP */
4257
4258 #ifdef TIZEN_FEATURE_BT_MEDIA_ENHANCE
4259 void _bt_ag_agent_check_transport_state(void)
4260 {
4261         FN_START;
4262
4263         if (transport_state == MEDIA_TRANSPORT_STATE_PLAYING) {
4264                 GDBusProxy *proxy;
4265                 GError *err = NULL;
4266
4267                 proxy =  g_dbus_proxy_new_sync(ag_dbus_conn,
4268                                 G_DBUS_PROXY_FLAGS_NONE, NULL,
4269                                 "org.pulseaudio.Server", A2DP_SOURCE_ENDPOINT,
4270                                 BLUEZ_MEDIA_ENDPOINT_INTERFACE, NULL, &err);
4271
4272                 if (!proxy) {
4273                         if (err) {
4274                                 ERR("Unable to create proxy: %s", err->message);
4275                                 g_clear_error(&err);
4276                         }
4277                         return;
4278                 }
4279                 INFO_C("SuspendMedia initiated");
4280
4281                 g_dbus_proxy_call(proxy,
4282                                         "SuspendMedia", NULL,
4283                                         G_DBUS_CALL_FLAGS_NONE, 2000,
4284                                         NULL, NULL, NULL);
4285                 transport_state = MEDIA_TRANSPORT_STATE_IDLE;
4286         }
4287
4288         FN_END;
4289 }
4290
4291 static void __bt_ag_agent_transport_state_update(const char *value)
4292 {
4293
4294         if (!g_strcmp0(value, "idle"))
4295                 transport_state = MEDIA_TRANSPORT_STATE_IDLE;
4296         else if (!g_strcmp0(value, "pending") || !g_strcmp0(value, "active"))
4297                 transport_state = MEDIA_TRANSPORT_STATE_PLAYING;
4298         else
4299                 transport_state =  MEDIA_TRANSPORT_STATE_DISCONNECTED;
4300
4301         INFO_C("transport_state %d", transport_state);
4302 }
4303
4304 static void __bt_ag_agent_media_filter_cb(GDBusConnection *connection,
4305                                         const gchar *sender_name,
4306                                         const gchar *object_path,
4307                                         const gchar *interface_name,
4308                                         const gchar *signal_name,
4309                                         GVariant *parameters,
4310                                         gpointer user_data)
4311 {
4312         FN_START;
4313         char *inter = NULL;
4314         GVariant *dict_param = NULL;
4315         GVariant *optional_param = NULL;
4316
4317         if (strcasecmp(signal_name, "PropertiesChanged") == 0) {
4318                 if (g_strcmp0(g_variant_get_type_string(parameters),
4319                                                         "(sa{sv}as)")) {
4320                         ERR("Incorrect parameters\n");
4321                         return;
4322                 }
4323
4324                 g_variant_get(parameters, "(&s@a{sv}@as)",
4325                                         &inter, &dict_param, &optional_param);
4326                 if (dict_param && (!g_strcmp0(inter,
4327                                 BLUEZ_MEDIA_TRANSPORT_INTERFACE))){
4328                         GVariantIter *iter = NULL;
4329                         const gchar *key = NULL;
4330                         GVariant *value_var = NULL;
4331                         gchar *value = NULL;
4332                         g_variant_get(dict_param, "a{sv}", &iter);
4333                         while (g_variant_iter_loop(
4334                                         iter, "{sv}", &key, &value_var)) {
4335                                 DBG("key %s", key);
4336                                 if (g_strcmp0(key, "State") == 0) {
4337                                         value = (gchar *)g_variant_get_string(
4338                                                                 value_var,
4339                                                                 NULL);
4340                                         DBG("value %s", value);
4341                                         __bt_ag_agent_transport_state_update(value);
4342                                         break;
4343                                 }
4344                         }
4345                         g_variant_iter_free(iter);
4346                 }
4347         } else if (strcasecmp(signal_name, "ProfileStateChanged") == 0) {
4348                 char *profile_uuid = NULL;
4349                 int state = 0;
4350
4351                 g_variant_get(parameters, "(&si)", &profile_uuid, &state);
4352                 if ((g_strcmp0(profile_uuid, A2DP_SINK_UUID) == 0)  &&
4353                         (state == BT_PROFILE_STATE_DISCONNECTED)) {
4354                         DBG("Updating the transport state");
4355                         __bt_ag_agent_transport_state_update("Disconnect");
4356                 }
4357         }
4358
4359         if (dict_param)
4360                 g_variant_unref(dict_param);
4361
4362         if (optional_param)
4363                 g_variant_unref(optional_param);
4364
4365         FN_END;
4366 }
4367 #endif
4368
4369 /* LCOV_EXCL_START */
4370 static void __bt_ag_agent_dbus_init(void)
4371 {
4372         FN_START;
4373
4374         if (__bt_ag_get_gdbus_connection() == NULL) {
4375                 ERR("Error in creating the gdbus connection\n");
4376                 return;
4377         }
4378         if (!__bt_ag_register_profile_methods()) {
4379                 ERR("Error in HFP / HSP register_profile_methods\n");
4380                 return;
4381         }
4382
4383         if (!__bt_ag_agent_get_adapter_path(ag_dbus_conn , NULL)) {
4384
4385                 gchar *path = g_strdup(BT_AG_AGENT_OBJECT_PATH);
4386                 __bt_ag_agent_register(path, hfp_ver,
4387                          HFP_AG_UUID, "Hands-Free Audio Gateway");
4388
4389                 path = g_strdup(BT_HS_AG_AGENT_OBJECT_PATH);
4390                 __bt_ag_agent_register(path, hsp_ver,
4391                         HSP_AG_UUID, "Headset Audio Gateway");
4392         }
4393
4394         interface_added_sig_id = g_dbus_connection_signal_subscribe(ag_dbus_conn,
4395                                 NULL, BT_MANAGER_INTERFACE,
4396                                 BT_INTERFACES_ADDED, NULL, NULL, 0,
4397                                 __bt_ag_agent_filter_cb, NULL, NULL);
4398
4399         interface_removed_sig_id = g_dbus_connection_signal_subscribe(ag_dbus_conn,
4400                                 NULL, BT_MANAGER_INTERFACE,
4401                                 BT_INTERFACES_REMOVED, NULL, NULL, 0,
4402                                 __bt_ag_agent_filter_cb, NULL, NULL);
4403
4404 #ifdef TIZEN_FEATURE_BT_MEDIA_ENHANCE
4405         media_sig_id = g_dbus_connection_signal_subscribe(ag_dbus_conn,
4406                                 NULL, BT_PROPERTIES_INTERFACE, NULL, NULL,
4407                                 NULL, 0, __bt_ag_agent_media_filter_cb,
4408                                 NULL, NULL);
4409
4410         media_state_sig_id = g_dbus_connection_signal_subscribe(ag_dbus_conn,
4411                                 NULL, BLUEZ_DEVICE_INTERFACE, NULL, NULL,
4412                                 NULL, 0, __bt_ag_agent_media_filter_cb,
4413                                 NULL, NULL);
4414
4415         transport_state = MEDIA_TRANSPORT_STATE_DISCONNECTED;
4416 #endif
4417         FN_END;
4418         return;
4419 }
4420 /* LCOV_EXCL_STOP */
4421
4422 static uint32_t __bt_ag_agent_get_ag_features(void)
4423 {
4424
4425         uint32_t ag_features;
4426
4427         if (TIZEN_MODEL_NAME_TM1) {
4428                 ag_features = BT_AG_FEATURE_EC_AND_NR |
4429                                 BT_AG_FEATURE_REJECT_CALL |
4430                                 BT_AG_FEATURE_ENHANCED_CALL_STATUS |
4431                                 BT_AG_FEATURE_THREE_WAY_CALL |
4432                                 BT_AG_FEATURE_EXTENDED_ERROR_RESULT_CODES;
4433         } else {
4434                 ag_features = BT_AG_FEATURE_EC_AND_NR |
4435                                 BT_AG_FEATURE_REJECT_CALL |
4436                                 BT_AG_FEATURE_ENHANCED_CALL_STATUS |
4437                                 BT_AG_FEATURE_THREE_WAY_CALL |
4438                                 BT_AG_FEATURE_VOICE_RECOGNITION |
4439                                 BT_AG_FEATURE_EXTENDED_ERROR_RESULT_CODES;
4440         }
4441
4442         wbs_en = TRUE;
4443 #if defined(TIZEN_FEATURE_BT_HFP_AG)
4444         hfp_ver = HFP_VERSION_1_7;
4445 #else
4446         hfp_ver = HFP_VERSION_1_5;
4447 #endif
4448         hsp_ver = HSP_VERSION_1_2;
4449
4450         if (hfp_ver > HFP_VERSION_1_5)
4451                 ag_features |= BT_AG_FEATURE_CODEC_NEGOTIATION;
4452         if (hfp_ver == HFP_VERSION_1_7)
4453                 ag_features |= BT_AG_FEATURE_ESCO_S4_T2_SUPPORT;
4454
4455         return ag_features;
4456 }
4457
4458 /* LCOV_EXCL_START */
4459 void *__bt_ag_agent_telephony_init(void *arg)
4460 {
4461
4462         int tapi_result;
4463         uint32_t ag_features = *((uint32_t *)arg);
4464
4465         INFO_C("Initializing the telephony info");
4466
4467         _bt_hfp_initialize_telephony_manager(ag_features);
4468         __bt_ag_agent_subscribe_vconf_updates();
4469
4470         tapi_handle = tel_init(NULL);
4471         tapi_result = tel_get_sim_msisdn(tapi_handle, __bt_ag_agent_tel_cb,
4472                                         NULL);
4473         if (tapi_result != TAPI_API_SUCCESS)
4474                 ERR("Fail to get sim info: %d", tapi_result);
4475         return NULL;
4476 }
4477
4478 int main(void)
4479 {
4480         int i;
4481         uint32_t ag_features;
4482         struct sigaction sa;
4483         pthread_t thread_id = 0;
4484
4485         INFO_C("### Starting Bluetooth AG agent");
4486
4487         ag_features = __bt_ag_agent_get_ag_features();
4488
4489         ag.sdp_features = (uint16_t) ag_features & 0x1F;
4490
4491         if (hfp_ver >= HFP_VERSION_1_6 && wbs_en == TRUE)
4492                 ag.sdp_features |= BT_AG_FEATURE_SDP_WIDEBAND_SPEECH;
4493
4494         memset(&sa, 0, sizeof(sa));
4495         sa.sa_flags = SA_NOCLDSTOP;
4496         sa.sa_handler = __bt_ag_agent_sigterm_handler;
4497
4498         for (i = 0; i < BT_AG_SIG_NUM; i++)
4499                 sigaction(bt_ag_sig_to_handle[i], &sa, &(bt_ag_sigoldact[i]));
4500
4501         gmain_loop = g_main_loop_new(NULL, FALSE);
4502
4503         if (gmain_loop == NULL) {
4504                 ERR("GMainLoop create failed");
4505                 return EXIT_FAILURE;
4506         }
4507
4508         __bt_ag_agent_dbus_init();
4509         if (pthread_create(&thread_id, NULL,
4510                         (void *)&__bt_ag_agent_telephony_init,
4511                                         &ag_features) < 0) {
4512                 ERR("pthread_create() is failed");
4513                 return EXIT_FAILURE;
4514         }
4515
4516         if (pthread_detach(thread_id) < 0)
4517                 ERR("pthread_detach() is failed");
4518
4519         g_main_loop_run(gmain_loop);
4520
4521         DBG("Cleaning up");
4522
4523         tel_deinit(tapi_handle);
4524
4525         __bt_ag_agent_dbus_deinit();
4526         _bt_hfp_deinitialize_telephony_manager();
4527         __bt_ag_agent_release_vconf_updates();
4528
4529         if (remote_dev_path)
4530                 g_free(remote_dev_path);
4531
4532         if (gmain_loop)
4533                 g_main_loop_unref(gmain_loop);
4534
4535         INFO_C("### Terminating Bluetooth AG agent");
4536         return 0;
4537 }
4538 /* LCOV_EXCL_STOP */