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