Update HF agent codes for wearable 30/188730/3 accepted/tizen_5.0_unified accepted/tizen/5.0/unified/20181102.015434 accepted/tizen/unified/20180913.064020 accepted/tizen/unified/20180914.073143 submit/tizen/20180912.234844 submit/tizen/20180913.053639 submit/tizen_5.0/20181101.000003
authorWootak Jung <wootak.jung@samsung.com>
Thu, 6 Sep 2018 06:16:31 +0000 (15:16 +0900)
committerWootak Jung <wootak.jung@samsung.com>
Mon, 10 Sep 2018 07:07:11 +0000 (16:07 +0900)
Change-Id: Ibed6e269eab908c436d0eb8ab5a0b208d762fac0

hf-agent/bluetooth-hf-agent.c
hf-agent/bluetooth-hf-agent.h

index 8c2857c..e66ed10 100755 (executable)
@@ -43,7 +43,7 @@
 #include "bluetooth-agent-profile.h"
 
 #define BT_AGENT_SYSPOPUP_MAX_ATTEMPT 3
-#define CALL_APP_ID "org.tizen.call-ui"
+#define CALL_ALIAS_APP_ID "org.tizen.call-ui"
 
 #define MAX_WAITING_DELAY 8
 #define READ_TX_POWER_MIN -30
 static GMainLoop *gmain_loop = NULL;
 static char *g_obj_path;
 
-static GDBusConnection *gdbus_conn;
-static GDBusProxy *service_gproxy;
+static GDBusConnection *gdbus_conn = NULL;
+static GDBusProxy *profile_gproxy = NULL;
 static guint interface_added_sig_id;
 static guint interface_removed_sig_id;
 int g_id = 0;
 uint16_t hf_ver;
 
+guint clcc_timer = 0;
+int clcc_retry_count = 0;
+guint clcc_async_timer = 0;
+int clcc_async_retry_count = 0;
+#define CLCC_RETRY_COUNT 10
+#define CLCC_RETRY_TIMER 100   /* 100 msec */
+
 #define HFP_HF_UUID "0000111e-0000-1000-8000-00805f9b34fb"
 #define DEFAULT_ADAPTER_OBJECT_PATH "/org/bluez/hci0"
 
@@ -103,6 +110,8 @@ static const gchar hf_agent_introspection_xml[] =
 "               <method name='VoiceRecognition'>"
 "                       <arg type='i' name='status' direction='in'/>"
 "               </method>"
+"               <method name='ScoConnect'>"
+"               </method>"
 "               <method name='ScoDisconnect'>"
 "               </method>"
 "               <method name='SpeakerGain'>"
@@ -129,16 +138,21 @@ static const gchar hf_agent_introspection_xml[] =
 "                      <arg type='i' name='count' direction='out'/>"
 "                      <arg type='a(siiii)' name='callList' direction='out'/>"
 "               </method>"
+"               <method name='RequestCallListAsync'>"
+"               </method>"
 "               <method name='GetAudioConnected'>"
 "                      <arg type='i' name='status' direction='out'/>"
 "               </method>"
 "               <method name='IsHfConnected'>"
 "                      <arg type='b' name='status' direction='out'/>"
 "               </method>"
+"               <method name='IsInbandRingtoneSupported'>"
+"                      <arg type='b' name='status' direction='out'/>"
+"               </method>"
 " </interface>"
 "</node>";
 
-static bt_hf_agent_info_t bt_hf_info;
+static bt_hf_agent_info_t bt_hf_info = {0,};
 static gboolean is_hf_connected = FALSE;
 static int32_t current_codec_id = BT_HF_CODEC_ID_CVSD;
 static int32_t sco_audio_connected = BT_HF_AUDIO_DISCONNECTED;
@@ -158,6 +172,10 @@ typedef struct {
        char *number;
 } hf_call_list_info_t;
 
+#define BT_HF_SIG_NUM 3
+static struct sigaction bt_hf_sigoldact[BT_HF_SIG_NUM];
+static int bt_hf_sig_to_handle[] = { SIGABRT, SIGSEGV, SIGTERM };
+
 static GError *__bt_hf_agent_set_error(bt_hf_agent_error_t error);
 
 static gboolean __bt_hf_agent_emit_property_changed(
@@ -191,6 +209,7 @@ static gboolean __bt_get_current_indicators(bt_hf_agent_info_t *bt_hf_info);
 static gboolean __bt_get_supported_indicators(bt_hf_agent_info_t *bt_hf_info);
 static gboolean __bt_hf_agent_connection(gint32 fd, const gchar * object_path);
 static gboolean __bt_hf_agent_connection_release(void);
+static void __bt_hf_agent_handle_call_list(bt_hf_agent_info_t *bt_hf_info);
 
 struct indicator {
        gchar descr[BT_HF_INDICATOR_DESCR_SIZE];
@@ -211,6 +230,8 @@ static int _hf_agent_send_3way_cmd(GDBusMethodInvocation *context, char *cmd);
 static int _hf_agent_voice_recognition(GDBusMethodInvocation *context,
                                                        unsigned int status);
 
+static gboolean bt_hf_agent_sco_connect(void);
+
 static gboolean bt_hf_agent_sco_disconnect(void);
 
 static int _hf_agent_send_dtmf(GDBusMethodInvocation *context, char *dtmf);
@@ -221,7 +242,13 @@ static int bt_hf_agent_send_at_cmd(GDBusMethodInvocation *context, char *atcmd);
 
 static int hf_handle_rx_at_cmd(bt_hf_agent_info_t *bt_hf_info, const char *buf);
 
-void __bt_hf_agent_print_at_buffer(char *message, const char *buf)
+static void __on_log_glib(const gchar *log_domain, GLogLevelFlags log_level,
+               const gchar *msg, gpointer user_data)
+{
+       ERR_C("%s", msg);
+}
+
+static void __bt_hf_agent_print_at_buffer(char *message, const char *buf)
 {
 
        int i = 0;
@@ -327,6 +354,9 @@ static GError *__bt_hf_agent_set_error(bt_hf_agent_error_t error)
        case BT_HF_AGENT_ERROR_NO_MEMORY:
                return g_error_new(BT_HF_AGENT_ERROR, error,
                                        BT_ERROR_NO_MEMORY);
+       case BT_HF_AGENT_ERROR_NO_DATA:
+               return g_error_new(BT_HF_AGENT_ERROR, error,
+                                       BT_ERROR_NO_DATA);
        case BT_HF_AGENT_ERROR_I_O_ERROR:
                return g_error_new(BT_HF_AGENT_ERROR, error,
                                        BT_ERROR_I_O_ERROR);
@@ -371,6 +401,64 @@ static void __bt_hf_unlock_display()
                ERR("deviced error!");
 }
 
+static gboolean __clcc_timer_func(gpointer data)
+{
+       GVariant *call_var;
+       GError *err;
+
+       DBG("+");
+
+       if (bt_hf_info.state != BT_HF_STATE_CONNECTED) {
+               DBG("NOT CONNECTED");
+               err = __bt_hf_agent_set_error(BT_HF_AGENT_ERROR_NOT_CONNECTED);
+               g_dbus_method_invocation_return_gerror((GDBusMethodInvocation *) data, err);
+               g_error_free(err);
+               clcc_timer = 0;
+               return FALSE;
+       }
+
+       if (send_flag && clcc_retry_count > 0) {
+               clcc_retry_count--;
+               DBG("Still pending. try later (remained [%d] times)", clcc_retry_count);
+               return TRUE;
+       }
+
+       clcc_timer = 0;
+
+       call_var = bt_hf_agent_request_call_list();
+       if (!call_var) {
+               INFO("NOT AVAILABLE");
+               err = __bt_hf_agent_set_error(BT_HF_AGENT_ERROR_NOT_AVAILABLE);
+               g_dbus_method_invocation_return_gerror((GDBusMethodInvocation *) data, err);
+               g_error_free(err);
+               return FALSE;
+       }
+
+       INFO("return call list info");
+       g_dbus_method_invocation_return_value((GDBusMethodInvocation *) data, call_var);
+       return FALSE;
+}
+
+static gboolean __clcc_async_timer_func(gpointer data)
+{
+       DBG("+");
+
+       if (send_flag && clcc_async_retry_count > 0) {
+               clcc_async_retry_count--;
+               ERR("Still pending. try later (remained [%d] times)", clcc_async_retry_count);
+               return TRUE;
+       }
+
+       clcc_async_timer = 0;
+
+       __bt_hf_agent_handle_call_list(&bt_hf_info);
+       g_dbus_method_invocation_return_value((GDBusMethodInvocation*)data, NULL);
+
+       INFO("update_call_list succeeded");
+
+       return FALSE;
+}
+
 static void __hf_agent_method(GDBusConnection *connection,
                            const gchar *sender,
                            const gchar *object_path,
@@ -466,6 +554,14 @@ static void __hf_agent_method(GDBusConnection *connection,
                if (ret)
                        goto fail;
 
+       } else if (g_strcmp0(method_name, "ScoConnect") == 0) {
+               DBG("Going to call ScoConnect");
+               if (!bt_hf_agent_sco_connect()) {
+                       ret = BT_HF_AGENT_ERROR_INTERNAL;
+                       goto fail;
+               }
+
+               g_dbus_method_invocation_return_value(context, NULL);
        } else if (g_strcmp0(method_name, "ScoDisconnect") == 0) {
                DBG("Going to call ScoDisconnect");
                if (!bt_hf_agent_sco_disconnect()) {
@@ -501,9 +597,10 @@ static void __hf_agent_method(GDBusConnection *connection,
                g_variant_get(parameters, "(&s)", &cmd);
 
                DBG("Going to call SendAtCmd\n");
-               ret = bt_hf_agent_send_at_cmd(context, cmd);
+               ret = bt_hf_agent_send_at_cmd(NULL, cmd);
                if (ret)
                        goto fail;
+               g_dbus_method_invocation_return_value(context, NULL);
 
        } else if (g_strcmp0(method_name, "ReleaseAndAccept") == 0) {
                DBG("Going to call ReleaseAndAccept");
@@ -539,13 +636,45 @@ static void __hf_agent_method(GDBusConnection *connection,
        } else if (g_strcmp0(method_name, "RequestCallList") == 0) {
                GVariant *call_var;
 
-               DBG("Going to call RequestCallList");
-               call_var = bt_hf_agent_request_call_list();
-               if (!call_var) {
+               INFO("Going to call RequestCallList (send_flag[%d])", send_flag);
+
+               if (send_flag) {
+                       INFO("Send_flag is true. Try to send CLCC later");
+                       clcc_retry_count = CLCC_RETRY_COUNT;
+                       clcc_timer = g_timeout_add(CLCC_RETRY_TIMER, __clcc_timer_func, context);
+               } else {
+                       call_var = bt_hf_agent_request_call_list();
+                       if (!call_var) {
+                               ret = BT_HF_AGENT_ERROR_NOT_AVAILABLE;
+                               goto fail;
+                       }
+                       g_dbus_method_invocation_return_value(context, call_var);
+               }
+       } else if (g_strcmp0(method_name, "RequestCallListAsync") == 0) {
+               INFO("Going to call RequestCallListAsync (send_flag[%d])", send_flag);
+
+               if (clcc_async_timer > 0) {
                        ret = BT_HF_AGENT_ERROR_NOT_AVAILABLE;
                        goto fail;
                }
-               g_dbus_method_invocation_return_value(context, call_var);
+               if (bt_hf_info.state != BT_HF_STATE_CONNECTED) {
+                       ret = BT_HF_AGENT_ERROR_NOT_CONNECTED;
+                       goto fail;
+               }
+               if (bt_hf_info.ciev_call_status == 0 &&
+                       bt_hf_info.ciev_call_setup_status == 0) {
+                       ret = BT_HF_AGENT_ERROR_NO_DATA;
+                       goto fail;
+               }
+
+               if (send_flag) {
+                       INFO("Send_flag is true. Try to send CLCC later");
+                       clcc_async_retry_count = CLCC_RETRY_COUNT;
+                       clcc_async_timer = g_timeout_add(CLCC_RETRY_TIMER, __clcc_async_timer_func, context);
+               } else {
+                       __bt_hf_agent_handle_call_list(&bt_hf_info);
+                       g_dbus_method_invocation_return_value(context, NULL);
+               }
        } else if (g_strcmp0(method_name, "GetAudioConnected") == 0) {
                DBG("Going to call GetAudioConnected");
                g_dbus_method_invocation_return_value(context,
@@ -556,7 +685,25 @@ static void __hf_agent_method(GDBusConnection *connection,
 
                g_dbus_method_invocation_return_value(context,
                                g_variant_new("(b)", is_hf_connected));
+       } else if (g_strcmp0(method_name, "IsInbandRingtoneSupported") == 0) {
+               gboolean is_supported = FALSE;
+
+               if (is_hf_connected == FALSE) {
+                       ret = BT_HF_AGENT_ERROR_NOT_CONNECTED;
+                       goto fail;
+               }
+
+               if (bt_hf_info.inband_ringtone_support)
+                       is_supported = TRUE;
+               else
+                       is_supported = FALSE;
+
+               INFO("IsInbandRingtoneSupported : %s", is_supported ?
+                               "Supported" : "NotSupported");
+               g_dbus_method_invocation_return_value(context,
+                               g_variant_new("(b)", is_supported));
        }
+
        INFO("-");
        return;
 
@@ -684,8 +831,7 @@ static gboolean __bt_hf_register_profile_methods(void)
        return TRUE;
 }
 
-static GDBusProxy *__bt_hf_gdbus_init_service_proxy(const gchar *service,
-                               const gchar *path, const gchar *interface)
+static GDBusProxy *__bt_hf_gdbus_init_profile_proxy(void)
 {
        DBG("+");
 
@@ -701,8 +847,8 @@ static GDBusProxy *__bt_hf_gdbus_init_service_proxy(const gchar *service,
 
        proxy =  g_dbus_proxy_new_sync(conn,
                        G_DBUS_PROXY_FLAGS_NONE, NULL,
-                       service, path,
-                       interface, NULL, &err);
+                       BLUEZ_SERVICE_NAME, "/org/bluez",
+                       BLUEZ_PROFILE_MGMT_INTERFACE, NULL, &err);
 
        if (!proxy) {
                if (err) {
@@ -712,16 +858,48 @@ static GDBusProxy *__bt_hf_gdbus_init_service_proxy(const gchar *service,
                return NULL;
        }
 
+       profile_gproxy = proxy;
+
        DBG("-");
        return proxy;
 }
 
+static GDBusProxy *__bt_hf_gdbus_get_profile_proxy(void)
+{
+       return (profile_gproxy) ? profile_gproxy :
+                                 __bt_hf_gdbus_init_profile_proxy();
+}
+
 static GDBusProxy *__bt_hf_gdbus_get_service_proxy(const gchar *service,
                                const gchar *path, const gchar *interface)
 {
-       return (service_gproxy) ? service_gproxy :
-                       __bt_hf_gdbus_init_service_proxy(service,
-                                       path, interface);
+       DBG("+");
+
+       GDBusProxy *proxy;
+       GError *err = NULL;
+       GDBusConnection *conn;
+
+       conn = __bt_hf_get_gdbus_connection();
+       if (!conn) {
+               ERR("Unable to get connection");
+               return NULL;
+       }
+
+       proxy =  g_dbus_proxy_new_sync(conn,
+                       G_DBUS_PROXY_FLAGS_NONE, NULL,
+                       service, path,
+                       interface, NULL, &err);
+
+       if (!proxy) {
+               if (err) {
+                       ERR("Unable to create proxy: %s", err->message);
+                        g_clear_error(&err);
+               }
+               return NULL;
+       }
+
+       DBG("-");
+       return proxy;
 }
 
 static char __bt_hf_agent_get_tx_power(char *address)
@@ -750,11 +928,14 @@ static char __bt_hf_agent_get_tx_power(char *address)
                                                error->code, error->message);
                        g_clear_error(&error);
                }
+               g_object_unref(proxy);
                return result;
        }
        g_variant_get(ret, "(y)", &result);
        DBG("TX power level = %d", result);
        g_variant_unref(ret);
+       g_object_unref(proxy);
+
        return result;
 }
 
@@ -786,10 +967,12 @@ static int __bt_hf_agent_gdbus_method_send(const char *service,
 
                        g_clear_error(&error);
                }
+               g_object_unref(proxy);
                return BT_HF_AGENT_ERROR_INTERNAL;
        }
 
        g_variant_unref(ret);
+       g_object_unref(proxy);
 
        return BT_HF_AGENT_ERROR_NONE;
 }
@@ -850,7 +1033,7 @@ static gboolean __bt_hf_monitor_timer_cb(gpointer data)
 gboolean __bt_hf_agent_add_queue(GDBusMethodInvocation *context, char *at,
                                        int count, gboolean pending_flag)
 {
-       int i, len;
+       int i, len, timer_id;
        if (bt_hf_info.slc == FALSE)
                return FALSE;
 
@@ -868,17 +1051,22 @@ gboolean __bt_hf_agent_add_queue(GDBusMethodInvocation *context, char *at,
        len = g_slist_length(bt_hf_info.cmd_send_queue);
        for (i = 0; i < len; ++i) {
                cmd = g_slist_nth_data(bt_hf_info.cmd_send_queue, i);
-               DBG("Q> %.6s[%d]", cmd->at_cmd, cmd->id);
+               if (cmd)
+                       DBG("Q> %.6s[%d]", cmd->at_cmd, cmd->id);
        }
 
        /* We need to have base timeout + tolerance value to process other request */
        if (strstr(at, "ATD") || strstr(at, "BLDN")) {
                /* Android 15 seconds timeout in case of ATD timeout in flight mode */
-               cmd->timer_id = g_timeout_add_seconds(BT_HF_COMMAND_TIMEOUT * 5 + len,
+               timer_id = g_timeout_add_seconds(BT_HF_COMMAND_TIMEOUT * 5 + len,
                                         __bt_hf_monitor_timer_cb, cmd);
+               if (cmd)
+                       cmd->timer_id = timer_id;
        } else {
-               cmd->timer_id = g_timeout_add_seconds(BT_HF_COMMAND_TIMEOUT + len,
+               timer_id = g_timeout_add_seconds(BT_HF_COMMAND_TIMEOUT + len,
                                         __bt_hf_monitor_timer_cb, cmd);
+               if (cmd)
+                       cmd->timer_id = timer_id;
        }
        return TRUE;
 }
@@ -923,7 +1111,7 @@ static gboolean __bt_hf_agent_emit_property_changed(
        ret =  g_dbus_connection_emit_signal(connection,
                                NULL, path, interface,
                                "PropertyChanged",
-                               g_variant_new("s(v)", name, property),
+                               g_variant_new("(sv)", name, property),
                                &error);
        if (!ret) {
                if (error != NULL) {
@@ -941,6 +1129,36 @@ static gboolean __bt_hf_agent_emit_property_changed(
 Below methods exposed to Bluez
 */
 
+static gboolean  __bt_hf_agent_launch_call_app(void)
+{
+       bundle *b;
+       bool is_running;
+
+       DBG("+");
+       app_manager_is_running(CALL_ALIAS_APP_ID, &is_running);
+       if (is_running) {
+               DBG("Call app is already started");
+               return TRUE;
+       }
+
+       b = bundle_create();
+       if (NULL == b) {
+               ERR("bundle_create() Failed");
+               return FALSE;
+       }
+
+       bundle_add(b, "launch-type", "BT_LAUNCH");
+
+       bundle_add(b, "carrier-type", "BT");
+       DBG("For 3G, carrier-type: BT has been added");
+       aul_launch_app_async(CALL_ALIAS_APP_ID, b);
+       bundle_free(b);
+
+       INFO("-aul_launch_app_async -");
+
+       return TRUE;
+}
+
 static void __bt_hf_agent_handle_ind_change(bt_hf_agent_info_t *bt_hf_info,
                                                        guint index, gint value)
 {
@@ -977,27 +1195,52 @@ static void __bt_hf_agent_handle_ind_change(bt_hf_agent_info_t *bt_hf_info,
                                        BT_HF_SERVICE_INTERFACE,
                                        "CallEnded", NULL);
                        bt_hf_info->call_active = FALSE;
+
+                       if (bt_hf_info->ciev_call_setup_status == 0) {
+                               __bt_hf_agent_emit_signal(gdbus_conn,
+                                               BT_HF_AGENT_OBJECT_PATH,
+                                               BT_HF_SERVICE_INTERFACE,
+                                               "CallIdle", NULL);
+                       }
                }
 
        } else if (!strcmp(name, "\"callsetup\"")) {
                bt_hf_info->ciev_call_setup_status = value;
                if (value == 0 && bt_hf_info->is_dialing) {
+                       bt_hf_info->is_dialing = FALSE;
                        __bt_hf_agent_emit_signal(conn,
                                        BT_HF_AGENT_OBJECT_PATH,
                                        BT_HF_SERVICE_INTERFACE,
                                        "CallTerminated",
                                        NULL);
-                       bt_hf_info->is_dialing = FALSE;
-               } else if (!bt_hf_info->is_dialing && value > 0)
+               } else if (!bt_hf_info->is_dialing && value > 0) {
                        bt_hf_info->is_dialing = TRUE;
+               }
 
-               if (bt_hf_info->ciev_call_status == 0 &&
-                                               bt_hf_info->ciev_call_setup_status == 0)
+               if (bt_hf_info->ciev_call_setup_status == 1) {
                        __bt_hf_agent_emit_signal(gdbus_conn,
                                        BT_HF_AGENT_OBJECT_PATH,
                                        BT_HF_SERVICE_INTERFACE,
-                                       "CallEnded", NULL);
-
+                                       "CallSetupIncoming", NULL);
+                       if (__bt_hf_agent_launch_call_app()  == FALSE)
+                               DBG("call app launching failed");
+               } else if (bt_hf_info->ciev_call_setup_status == 2) {
+                       __bt_hf_agent_emit_signal(gdbus_conn,
+                                       BT_HF_AGENT_OBJECT_PATH,
+                                       BT_HF_SERVICE_INTERFACE,
+                                       "CallSetupDialing", NULL);
+               } else if (bt_hf_info->ciev_call_setup_status == 3) {
+                       __bt_hf_agent_emit_signal(gdbus_conn,
+                                       BT_HF_AGENT_OBJECT_PATH,
+                                       BT_HF_SERVICE_INTERFACE,
+                                       "CallSetupAlerting", NULL);
+               } else  if (bt_hf_info->ciev_call_status == 0 &&
+                                               bt_hf_info->ciev_call_setup_status == 0) {
+                       __bt_hf_agent_emit_signal(gdbus_conn,
+                                       BT_HF_AGENT_OBJECT_PATH,
+                                       BT_HF_SERVICE_INTERFACE,
+                                               "CallIdle", NULL);
+               }
        } else if (!strcmp(name, "\"callheld\"")) {
                if (value == 0) { /* No calls held*/
                        __bt_hf_agent_emit_signal(conn,
@@ -1011,72 +1254,47 @@ static void __bt_hf_agent_handle_ind_change(bt_hf_agent_info_t *bt_hf_info,
                                        BT_HF_AGENT_OBJECT_PATH,
                                        BT_HF_SERVICE_INTERFACE,
                                        "CallsSwapped", NULL);
-                       bt_hf_info->is_dialing = FALSE;
                } else {
                        /*Call on hold, no active call*/
                        __bt_hf_agent_emit_signal(conn,
                                        BT_HF_AGENT_OBJECT_PATH,
                                        BT_HF_SERVICE_INTERFACE,
                                        "CallOnHold", NULL);
-                       bt_hf_info->is_dialing = FALSE;
                }
-       } else if (!strcmp(name, "\"service\""))
+       } else if (!strcmp(name, "\"service\"")) {
+               if (value < 0 || value > 1)
+                       ERR("Out of range");
+               else
                __bt_hf_agent_emit_property_changed(conn,
                                BT_HF_AGENT_OBJECT_PATH,
                                BT_HF_SERVICE_INTERFACE,
                                "RegistrationStatus",
-                               g_variant_new("(q)", value));
-       else if (!strcmp(name, "\"signal\""))
+                               g_variant_new("q", value));
+       } else if (!strcmp(name, "\"signal\"")) {
+               if (value < 0 || value > 5)
+                       ERR("Out of range");
+               else
                __bt_hf_agent_emit_property_changed(conn,
                                BT_HF_AGENT_OBJECT_PATH,
                                BT_HF_SERVICE_INTERFACE, "SignalStrength",
-                               g_variant_new("(q)", value));
-       else if (!strcmp(name, "\"roam\""))
+                               g_variant_new("q", value));
+       } else if (!strcmp(name, "\"roam\"")) {
+               if (value < 0 || value > 1)
+                       ERR("Out of range");
+               else
                __bt_hf_agent_emit_property_changed(conn,
                                BT_HF_AGENT_OBJECT_PATH,
                                BT_HF_SERVICE_INTERFACE, "RoamingStatus",
-                               g_variant_new("(q)", value));
-       else if (!strcmp(name, "\"battchg\""))
+                               g_variant_new("q", value));
+       } else if (!strcmp(name, "\"battchg\"")) {
+               if (value < 0 || value > 5)
+                       ERR("Out of range");
+               else
                __bt_hf_agent_emit_property_changed(conn,
                                BT_HF_AGENT_OBJECT_PATH,
                                BT_HF_SERVICE_INTERFACE, "BatteryCharge",
-                               g_variant_new("(q)", value));
-}
-
-
-static gboolean  __bt_hf_agent_launch_call_app(const char *launch_type,
-                                                       const char *number)
-{
-       bundle *b;
-       bool is_running;
-
-       DBG("+");
-       app_manager_is_running(CALL_APP_ID, &is_running);
-       if (is_running)
-               return FALSE;
-
-       DBG_SECURE("Launch type = %s, number(%s)", launch_type, number);
-
-       b = bundle_create();
-       if (NULL == b) {
-               ERR("bundle_create() Failed");
-               return FALSE;
+                               g_variant_new("q", value));
        }
-
-       bundle_add(b, "launch-type", launch_type);
-
-       if (strlen(number) != 0)
-               bundle_add(b, "number", number);
-
-       bundle_add(b, "carrier-type", "BT");
-       DBG("For 3G, carrier-type: BT has been added");
-
-       aul_launch_app(CALL_APP_ID, b);
-       bundle_free(b);
-
-       DBG("-");
-
-       return TRUE;
 }
 
 static void __bt_hf_agent_handle_voice_activation(gint value)
@@ -1114,13 +1332,55 @@ static void __bt_hf_agent_handle_speaker_gain(gint value)
        return;
 }
 
+static int __bt_hf_agent_handle_clip(bt_hf_agent_info_t *bt_hf_info,
+                                                       const gchar *buf)
+{
+       GDBusConnection *conn;
+       gchar *clip;
+       gchar number[BT_HF_CALLER_NUM_SIZE];
+       gchar *sep;
+       char fmt_str[BT_HF_FMT_STR_SIZE];
+       int len = strlen(buf);
+
+       DBG("__bt_hf_agent_handle_clip +");
+       if (len > BT_HF_CALLER_NUM_SIZE + 10) {
+               ERR("buf len %d is too long", len);
+               return 1;
+       }
+
+       if ((clip = strstr(buf, "\r\n+CLIP"))) {
+               snprintf(fmt_str, sizeof(fmt_str), "\r\n+CLIP: \"%%%ds", (int)(sizeof(number) - 1));
+               if (sscanf(clip, fmt_str, number) == 1) {
+                       sep = strchr(number, '"');
+                       sep[0] = '\0';
+
+                       clip = number;
+
+                       conn = __bt_hf_get_gdbus_connection();
+                       if (!conn) {
+                               ERR("Unable to get connection");
+                               return 1;
+                       }
+
+                       __bt_hf_agent_emit_signal(conn,
+                                       BT_HF_AGENT_OBJECT_PATH,
+                                       BT_HF_SERVICE_INTERFACE, "Ring",
+                                       g_variant_new("(s)", clip));
+               } else {
+                       ERR_SECURE("CLIP '%s' is Call Incoming", buf);
+                       return 1;
+               }
+       }
+       DBG("__bt_hf_agent_handle_clip -");
+       return 0;
+}
+
 static int __bt_hf_agent_handle_ccwa(bt_hf_agent_info_t *bt_hf_info,
                                                        const gchar *buf)
 {
        GDBusConnection *conn;
        gchar *ccwa;
-       gchar *number;
-       gchar *ptr;
+       gchar number[BT_HF_CALLER_NUM_SIZE];
        gchar *sep;
        char fmt_str[BT_HF_FMT_STR_SIZE];
        int len = strlen(buf);
@@ -1133,9 +1393,8 @@ static int __bt_hf_agent_handle_ccwa(bt_hf_agent_info_t *bt_hf_info,
 
        if ((ccwa = strstr(buf, "\r\n+CCWA"))) {
                snprintf(fmt_str, sizeof(fmt_str), "\r\n+CCWA: \"%%%ds",
-                                                                       BT_HF_CALLER_NUM_SIZE - 1);
-               if ((ptr = strstr(ccwa, "\"")) != NULL) {
-                       number = ptr + 1;
+                                                                       (int)(sizeof(number) - 1));
+               if (sscanf(ccwa, fmt_str, number) == 1) {
                        sep = strchr(number, '"');
                        sep[0] = '\0';
 
@@ -1160,6 +1419,19 @@ static int __bt_hf_agent_handle_ccwa(bt_hf_agent_info_t *bt_hf_info,
        return 0;
 }
 
+static void __bt_hf_agent_handle_bsir(bt_hf_agent_info_t *bt_hf_info,
+                                                       gint value)
+{
+       INFO("new value : %d", value);
+
+       if (value == 1)
+               bt_hf_info->inband_ringtone_support = TRUE;
+       else
+               bt_hf_info->inband_ringtone_support = FALSE;
+
+       return;
+}
+
 static GSList *__bt_hf_prepare_call_list(const char *buf)
 {
        GSList *call_list = NULL;
@@ -1167,7 +1439,6 @@ static GSList *__bt_hf_prepare_call_list(const char *buf)
        char *ptr = NULL;
        char *temp = NULL;
        char *sp;
-       char *stop;
        char delim_sep[] = "\r\n";
        char temp_buf[BT_HF_DATA_BUF_SIZE] = {0,};
 
@@ -1185,18 +1456,13 @@ static GSList *__bt_hf_prepare_call_list(const char *buf)
 
                call_info = g_new0(hf_call_list_info_t, 1);
 
-               /* str format : "+CLCC: %1d,%1d, %1d, %1d, %1d" */
-               if ((ptr = strchr(str, ':')) != NULL) {
-                       call_info->idx = strtol(ptr + 1, &stop, 10);
-                       call_info->dir = strtol(stop + 1, &stop, 10);
-                       call_info->status = strtol(stop + 1, &stop, 10);
-                       call_info->mode = strtol(stop + 1, &stop, 10);
-                       call_info->multi_party = strtol(stop + 1, &stop, 10);
-
-                       DBG("Index = [%d], Direction = [%d], Status = [%d], Mode = [%d], Multi_party = [%d]\n",
-                                       call_info->idx, call_info->dir, call_info->status,
-                                       call_info->mode, call_info->multi_party);
-               }
+               sscanf(str, "+CLCC: %1d,%1d, %1d, %1d, %1d",
+                               &call_info->idx, &call_info->dir,
+                               &call_info->status, &call_info->mode,
+                               &call_info->multi_party);
+               DBG("Index = [%d], Direction = [%d], Status = [%d], Mode = [%d], Multi_party = [%d]\n",
+                               call_info->idx, call_info->dir, call_info->status,
+                               call_info->mode, call_info->multi_party);
 
                ptr = strstr(str, "\"");
                if (ptr) {
@@ -1263,12 +1529,9 @@ static void __bt_hf_free_call_list(GSList *call_list)
        DBG("-");
 }
 
-static void __bt_hf_launch_call_using_call_list(GSList *call_list,
-                                       bt_hf_agent_info_t *bt_hf_info)
+static void __bt_hf_launch_call_using_call_list(GSList *call_list)
 {
        guint len;
-       const char *launch_type_str;
-       hf_call_list_info_t *call_info;
 
        DBG("+");
        if (call_list == NULL)
@@ -1276,26 +1539,9 @@ static void __bt_hf_launch_call_using_call_list(GSList *call_list,
 
        len = g_slist_length(call_list);
 
-       while (len--) {
-               call_info = g_slist_nth_data(call_list, len);
-
-               /* Launch based on below conditions
-                 * DC - Active call which is initiated from H
-                 * MR - Alerting call which is initiated from H
-                 * MT - Incoming call */
-               if (call_info->status == BT_HF_CALL_STAT_ACTIVE) {
-                       launch_type_str =  "DC";
-               } else {
-                       if (call_info->dir == BT_HF_CALL_DIR_INCOMING)
-                               launch_type_str =  "MT";
-                       else
-                               launch_type_str =  "MR";
-               }
+       if (len > 0 && __bt_hf_agent_launch_call_app() == FALSE)
+               DBG("call app launching failed");
 
-               if (__bt_hf_agent_launch_call_app(launch_type_str,
-                                       call_info->number)  == FALSE)
-                       DBG("call app launching failed");
-       }
        DBG("-");
 }
 
@@ -1317,14 +1563,16 @@ static GVariant *__bt_hf_agent_get_call_status_info(GSList *call_list)
 
        while (call_count--) {
                call_info = g_slist_nth_data(call_list, call_count);
-               INFO("Idx=%d, Dir=%d, status=%d, mode=%d, mparty=%d",
-               call_info->idx, call_info->dir, call_info->status,
-               call_info->mode, call_info->multi_party);
-               caller = call_info->number;
-
-               g_variant_builder_add(builder, "(siiii)",
-                               caller, call_info->dir, call_info->status,
-                               call_info->multi_party, call_info->idx);
+               if (call_info) {
+                       INFO("Idx=%d, Dir=%d, status=%d, mode=%d, mparty=%d",
+                       call_info->idx, call_info->dir, call_info->status,
+                       call_info->mode, call_info->multi_party);
+                       caller = call_info->number;
+
+                       g_variant_builder_add(builder, "(siiii)",
+                                       caller, call_info->dir, call_info->status,
+                                       call_info->multi_party, call_info->idx);
+               }
        }
        var_data = g_variant_new("(ia(siiii))",
                                g_slist_length(call_list), builder);
@@ -1349,19 +1597,17 @@ static void __bt_hf_agent_send_call_status_info(GSList *call_list)
        GDBusConnection *conn;
        GVariant *var_data;
 
-       var_data = __bt_hf_agent_get_call_status_info(call_list);
        conn = __bt_hf_get_gdbus_connection();
        if (!conn) {
                ERR("Unable to get connection");
-               return;
-       }
-
-       if (conn)
+       } else {
+               var_data = __bt_hf_agent_get_call_status_info(call_list);
                __bt_hf_agent_emit_signal(conn,
                                BT_HF_AGENT_OBJECT_PATH,
                                BT_HF_SERVICE_INTERFACE,
                                "CallStatusUpdate",
                                var_data);
+       }
 }
 
 static void __bt_hf_agent_handle_call_list(bt_hf_agent_info_t *bt_hf_info)
@@ -1381,31 +1627,6 @@ static void __bt_hf_agent_handle_call_list(bt_hf_agent_info_t *bt_hf_info)
        __bt_hf_unlock_display();
 }
 
-static void __bt_hf_agent_request_call_list_info(bt_hf_agent_info_t *bt_hf_info,
-                                                               guint index)
-{
-       char *name;
-       struct indicator *ind = g_slist_nth_data(bt_hf_info->indies, index - 1);
-       if (ind == NULL) {
-               ERR("Indicator is NULL");
-               return;
-       }
-       name = ind->descr;
-       DBG("name : %s", name);
-
-       if ((strcmp(name, "\"callsetup\"") != 0) &&
-                       (strcmp(name, "\"call\"") != 0) &&
-                               (strcmp(name, "\"callheld\"") != 0))
-               return;
-
-       __bt_hf_lock_display(0);
-
-       __bt_hf_agent_handle_call_list(bt_hf_info);
-
-       __bt_hf_unlock_display();
-
-}
-
 static gboolean __bt_hf_send_available_codec(bt_hf_agent_info_t *bt_hf_info, int send_only)
 {
        gchar buf[BT_HF_DATA_BUF_SIZE];
@@ -1472,33 +1693,36 @@ static void __bt_hf_agent_handle_codec_select(bt_hf_agent_info_t *bt_hf_info,
 {
        gchar cmd_buf[BT_HF_CMD_BUF_SIZE] = {0};
        gboolean ret;
+       int retval;
 
        if (codec_id != BT_HF_CODEC_ID_CVSD && codec_id != BT_HF_CODEC_ID_MSBC) {
                INFO("Codec id doesn't match, so send available codec again");
                ret = __bt_hf_send_available_codec(bt_hf_info, 1);
-               if (!ret)
+               if (FALSE == ret)
                        ERR("Failed to send avalable codec");
                return;
        }
 
        /* HF should be ready accpet SCO connection before sending theresponse for
        "\r\n+BCS=>Codec ID\r\n", Keep the BT chip ready to recevie encoded SCO data */
-       ret = _hf_agent_codec_setup(bt_hf_info->remote_addr, codec_id);
+       retval = _hf_agent_codec_setup(bt_hf_info->remote_addr, codec_id);
+       if (retval) {
+               ERR("_hf_agent_codec_setup : Failed [%d]", retval);
+       }
 
        snprintf(cmd_buf, sizeof(cmd_buf), BT_HF_CODEC_SELECT, codec_id);
 
        bt_hf_info->context = NULL;
-
        ret = __bt_hf_send_only(bt_hf_info, cmd_buf, strlen(cmd_buf));
-       if (!ret)
-               ERR("Failed to select the Codec");
+       if (FALSE == ret) {
+               ERR("__bt_hf_send_only : FALSE");
+       }
 }
 
 static int __bt_hf_agent_handler_ciev(bt_hf_agent_info_t *bt_hf_info, const char *buf)
 {
-       gchar *indicator;
+       gchar indicator[BT_HF_INDICATOR_DESCR_SIZE + 4];
        gchar *sep;
-       gchar *ptr;
        gint value;
        guint index;
        char fmt_str[BT_HF_FMT_STR_SIZE];
@@ -1507,21 +1731,13 @@ static int __bt_hf_agent_handler_ciev(bt_hf_agent_info_t *bt_hf_info, const char
 
        snprintf(fmt_str, sizeof(fmt_str), "\r\n+CIEV:%%%ds\r\n",
                                                                BT_HF_INDICATOR_DESCR_SIZE + 4 - 1);
-       if ((ptr = strchr(buf, ':')) != NULL) {
-               indicator = ptr + 1;
+       if (sscanf(buf, fmt_str, indicator) == 1) {
                sep = strchr(indicator, ',');
                sep[0] = '\0';
                sep += 1;
                index = atoi(indicator);
                value = atoi(sep);
                __bt_hf_agent_handle_ind_change(bt_hf_info, index, value);
-
-               if (bt_hf_info->ciev_call_status == 0 &&
-                               bt_hf_info->ciev_call_setup_status == 0)
-                       INFO("No active call");
-               else
-                       /* Request CLCC based on indicator change for call/callsetup/callHeld */
-                       __bt_hf_agent_request_call_list_info(bt_hf_info, index);
        }
        DBG("--------- __bt_hf_agent_handler_ciev ------------");
        return 0;
@@ -1558,6 +1774,7 @@ static int __bt_hf_agent_handler_ring(bt_hf_agent_info_t *bt_hf_info, const char
 static int __bt_hf_agent_handler_clip(bt_hf_agent_info_t *bt_hf_info, const char *buf)
 {
        DBG("+++++++++ __bt_hf_agent_handler_clip ++++++++");
+       __bt_hf_agent_handle_clip(bt_hf_info, buf);
        DBG("---------__bt_hf_agent_handler_clip --------");
 
        return 0;
@@ -1567,12 +1784,8 @@ static int __bt_hf_agent_handler_bvra(bt_hf_agent_info_t *bt_hf_info, const char
 {
        DBG("+++++++++ __bt_hf_agent_handler_bvra +++++++++");
        gint value;
-       gchar *ptr;
-       gchar *stop;
-       if ((ptr = strstr(buf, "BVRA:")) != NULL) {
-               value = strtol(ptr + 5, &stop, 10);
+        if (sscanf(buf, "\r\n+BVRA:%1d\r\n", &value) == 1)
                __bt_hf_agent_handle_voice_activation(value);
-       }
 
         DBG("---------__bt_hf_agent_handler_bvra --------");
        return 0;
@@ -1581,13 +1794,9 @@ static int __bt_hf_agent_handler_bvra(bt_hf_agent_info_t *bt_hf_info, const char
 static int __bt_hf_agent_handler_bcs(bt_hf_agent_info_t *bt_hf_info, const char *buf)
 {
        guint codec_id;
-       gchar *ptr;
-       gchar *stop;
        DBG("+++++++++ __bt_hf_agent_handler_bcs +++++++++-");
-       if ((ptr = strstr(buf, "BCS:")) != NULL) {
-               codec_id = strtol(ptr + 4, &stop, 10);
+       if (sscanf(buf, "\r\n+BCS:%3d\r\n", &codec_id))
                __bt_hf_agent_handle_codec_select(bt_hf_info, codec_id);
-       }
 
        DBG("---------__bt_hf_agent_handler_bcs --------");
        return 0;
@@ -1596,13 +1805,14 @@ static int __bt_hf_agent_handler_bcs(bt_hf_agent_info_t *bt_hf_info, const char
 static int __bt_hf_agent_handler_vgs(bt_hf_agent_info_t *bt_hf_info, const char *buf)
 {
        gint value;
-       gchar *ptr;
-       gchar *stop;
+       int ret = 0;
        DBG("+++++++++ __bt_hf_agent_handler_vgs +++++++++");
-       if ((ptr = strstr(buf, "VGS:")) != NULL) {
-               value = strtol(ptr + 4, &stop, 10);
+       if (buf[6] == ':')
+               ret = sscanf(buf, "\r\n+VGS:%2d\r\n", &value);
+       else if (buf[6] == '=')
+               ret = sscanf(buf, "\r\n+VGS=%2d\r\n", &value);
+       if (ret)
                __bt_hf_agent_handle_speaker_gain(value);
-       }
 
        DBG("---------__bt_hf_agent_handler_vgs --------");
 
@@ -1623,23 +1833,13 @@ static int __bt_hf_agent_handler_xsat(bt_hf_agent_info_t *bt_hf_info,
                                                        const char *buf)
 {
        gint app_id = 0;
-       char *msg = NULL;
+       char msg[BT_HF_DATA_BUF_SIZE];
        char fmt_str[BT_HF_CMD_BUF_SIZE];
-       char *ptr = NULL;
-       char *save_ptr = NULL;
-       char *stop = NULL;
 
        DBG("+++++++++ __bt_hf_agent_handler_xsat +++++++++");
        snprintf(fmt_str, sizeof(fmt_str), "\r\n+XSAT:%%d,%%%ds\r\n",
                                                                                (int)(sizeof(msg) - 1));
-       ptr = strstr(buf, "XSAT:");
-       if (ptr)
-               app_id = strtol(ptr + 5, &stop, 10);
-
-       if (stop)
-               msg = strtok_r(stop + 1, "\\", &save_ptr);
-
-       if (app_id > 0 && msg) {
+       if (sscanf(buf, fmt_str, &app_id, msg)) {
                if (app_id == 2 && strstr(msg, "READTXPOWER")) {
                        char cmd_buf[BT_HF_CMD_BUF_SIZE * 2] = {0, };
                        char power = __bt_hf_agent_get_tx_power(bt_hf_info->remote_addr);
@@ -1655,6 +1855,17 @@ static int __bt_hf_agent_handler_xsat(bt_hf_agent_info_t *bt_hf_info,
        return 0;
 }
 
+static int __bt_hf_agent_handler_bsir(bt_hf_agent_info_t *bt_hf_info, const char *buf)
+{
+       DBG("+++++++++ __bt_hf_agent_handler_bsir +++++++++");
+       gint value;
+        if (sscanf(buf, "\r\n+BSIR:%1d\r\n", &value) == 1)
+               __bt_hf_agent_handle_bsir(bt_hf_info, value);
+
+        DBG("---------__bt_hf_agent_handler_bsir --------");
+       return 0;
+}
+
 static int __bt_hf_agent_handler_cme_error(bt_hf_agent_info_t *bt_hf_info,
                                                        const char *buf)
 {
@@ -1672,7 +1883,7 @@ static int __bt_hf_agent_handler_cme_error(bt_hf_agent_info_t *bt_hf_info,
                __bt_hf_agent_emit_signal(conn,
                                        BT_HF_AGENT_OBJECT_PATH,
                                        BT_HF_SERVICE_INTERFACE,
-                                       "CallTerminated",
+                                       "FailedToDial",
                                        NULL);
        }
 
@@ -1706,7 +1917,7 @@ static int __bt_hf_agent_handler_response_err(bt_hf_agent_info_t *bt_hf_info,
 
                __bt_hf_agent_emit_signal(conn, BT_HF_AGENT_OBJECT_PATH,
                                        BT_HF_SERVICE_INTERFACE,
-                                       "CallTerminated",
+                                       "FailedToDial",
                                        NULL);
        }
        __bt_hf_clear_prev_sent_cmd();
@@ -1729,7 +1940,7 @@ static int __bt_hf_agent_handler_response_serr(bt_hf_agent_info_t *bt_hf_info,
 
                __bt_hf_agent_emit_signal(conn, BT_HF_AGENT_OBJECT_PATH,
                                        BT_HF_SERVICE_INTERFACE,
-                                       "CallTerminated",
+                                       "FailedToDial",
                                        NULL);
        }
 
@@ -1753,7 +1964,7 @@ static int __bt_hf_agent_handler_clcc(bt_hf_agent_info_t *bt_hf_info, const char
        if (call_list == NULL)
                goto done;
 
-       __bt_hf_launch_call_using_call_list(call_list, bt_hf_info);
+       __bt_hf_launch_call_using_call_list(call_list);
 
        __bt_hf_agent_send_call_status_info(call_list);
 
@@ -1765,20 +1976,21 @@ done:
        return 0;
 }
 
-static struct hf_event hf_event_callbacks[] = {
+static bt_hf_event hf_event_callbacks[] = {
        { "\r\n+CIEV:", __bt_hf_agent_handler_ciev },
        { "\r\nRING", __bt_hf_agent_handler_ring },
        { "\r\n+CLIP:", __bt_hf_agent_handler_clip },
        { "\r\n+BVRA:", __bt_hf_agent_handler_bvra },
        { "\r\n+BCS:", __bt_hf_agent_handler_bcs },
-       { "\r\n+VGS:", __bt_hf_agent_handler_vgs },
+       { "\r\n+VGS", __bt_hf_agent_handler_vgs },
        { "\r\n+CCWA:", __bt_hf_agent_handler_ccwa },
        { "\r\n+XSAT:", __bt_hf_agent_handler_xsat },
        {"\r\n+CLCC:", __bt_hf_agent_handler_clcc },
+       {"\r\n+BSIR:", __bt_hf_agent_handler_bsir },
        { 0 }
 };
 
-static struct hf_event hf_event_resp_callbacks[] = {
+static bt_hf_event hf_event_resp_callbacks[] = {
        { "\r\n+CME ERROR:", __bt_hf_agent_handler_cme_error },
        { "\r\nOK\r\n", __bt_hf_agent_handler_response_ok },
        { "ERROR", __bt_hf_agent_handler_response_err },
@@ -1794,7 +2006,8 @@ bt_hf_agent_send_at_info *__bt_hf_agent_find_next(bt_hf_agent_info_t *bt_hf_info
        len = g_slist_length(bt_hf_info->cmd_send_queue);
        for (i = 0; i < len; ++i) {
                cmd = g_slist_nth_data(bt_hf_info->cmd_send_queue, i);
-               DBG("F> %.6s[%d]", cmd->at_cmd, cmd->id);
+               if (cmd)
+                       DBG("F> %.6s[%d]", cmd->at_cmd, cmd->id);
        }
        len = g_slist_length(bt_hf_info->cmd_send_queue);
        DBG("Context queue length = %d", len);
@@ -1816,7 +2029,7 @@ bt_hf_agent_send_at_info *__bt_hf_agent_find_next(bt_hf_agent_info_t *bt_hf_info
 
 static int hf_handle_rx_at_cmd(bt_hf_agent_info_t *bt_hf_info, const char *buf)
 {
-       struct hf_event *ev;
+       bt_hf_event *ev;
        int ret = -EINVAL;
        bt_hf_agent_send_at_info *cmd = NULL;
 
@@ -1919,15 +2132,15 @@ static int hf_handle_append_clcc_buff(char *cmd_buf, const char *buf)
                        ERR("Invalid AT command signature..\n");
                        return 0;
                }
-               pos_end =  strstr(pos_end, "\r\n");
-               cmd_length =   (pos_end - pos_start) + 2;
+               pos_end = strstr(pos_end, "\r\n");
+               cmd_length = (pos_end - pos_start) + 2;
                INFO("CLCC balance Cmd Length = %d\n", cmd_length);
                memcpy(cmd_buf + cmd_buf_len, pos_start, cmd_length);
                cmd_buf[cmd_buf_len + cmd_length] = '\0';
 
                if (strstr(cmd_buf, "\r\nOK\r\n")) {
                        pos_end = strstr(datap, "\r\nOK\r\n");
-                       cmd_length =   (pos_end - pos_start);
+                       cmd_length = (pos_end - pos_start);
                        memcpy(cmd_buf + cmd_buf_len, pos_start, cmd_length);
                        cmd_buf[cmd_buf_len + cmd_length] = '\0';
                        INFO("New CLCC balance Cmd Length = %d", cmd_length);
@@ -1963,9 +2176,11 @@ static int hf_handle_rx_at_buff(bt_hf_agent_info_t *bt_hf_info, const char *buf)
                        ERR("Invalid AT command end signature..\n");
                        break;
                }
-               cmd_length =   (pos_end - pos_start) + 2;
+               cmd_length = (pos_end - pos_start) + 2;
                DBG("Cmd Length = %d\n", cmd_length);
 
+               if (cmd_length > BT_HF_DATA_BUF_SIZE - 1)
+                       return FALSE;
                memcpy(cmd_buf, pos_start, cmd_length);
                cmd_buf[cmd_length] = '\0';
 
@@ -2125,8 +2340,8 @@ static gboolean __bt_hf_send_only(bt_hf_agent_info_t *bt_hf_info, gchar *data,
                                        data);
 
        send_flag++;
-       DBG("Ref %d(after) on Send only buffer size =[%d] - Send <<<<<| %s",
-                                               send_flag, count, data);
+       DBG("Ref %d(after) on Send only buffer size =[%d] - Send <<<<<",
+                                               send_flag, count);
        return TRUE;
 }
 
@@ -2251,16 +2466,18 @@ static GSList *__bt_hf_parse_indicator_values(gchar *values, GSList *indices)
        GSList *runner = indices;
 
        gchar *cur = values - 1;
-       gchar *stop;
        DBG("Indicator string = %s", values);
        __bt_hf_agent_print_at_buffer("Indicator values :", values);
        while (cur != NULL) {
                cur += 1;
-               val = strtol(cur, &stop, 10);
+               sscanf(cur, "%1d", &val);
                cur = strchr(cur, ',');
                ind = g_slist_nth_data(runner, 0);
-               ind->value = val;
+               if (ind != NULL)
+                       ind->value = val;
                runner = g_slist_next(runner);
+               if (runner == NULL)
+                       break;
        }
        return indices;
 }
@@ -2293,7 +2510,7 @@ static guint __bt_hf_get_hold_mpty_features(gchar *features)
        return result;
 }
 
-static gboolean __bt_hf_agent_sco_conn_cb(GIOChannel *chan, GIOCondition cond, gpointer user_data)
+static gboolean __bt_hf_agent_sco_disconnect_cb(GIOChannel *chan, GIOCondition cond, gpointer user_data)
 {
        bt_hf_agent_info_t *bt_hf_info = user_data;
        GDBusConnection *conn;
@@ -2305,6 +2522,7 @@ static gboolean __bt_hf_agent_sco_conn_cb(GIOChannel *chan, GIOCondition cond, g
        if (cond & (G_IO_HUP | G_IO_ERR)) {
                g_io_channel_shutdown(chan, TRUE, NULL);
                close(bt_hf_info->cli_sco_fd);
+               bt_hf_info->cli_sco_fd = -1;
                g_io_channel_unref(chan);
                DBG("Emit AudioDisconnected Signal");
 
@@ -2326,21 +2544,6 @@ static gboolean __bt_hf_agent_sco_conn_cb(GIOChannel *chan, GIOCondition cond, g
        return TRUE;
 }
 
-static gboolean __bt_agent_query_and_update_call_list(gpointer data)
-{
-       DBG("+");
-       bt_hf_agent_info_t *bt_hf_info = data;
-
-       if (bt_hf_info->cli_sco_fd >= 0)
-               __bt_hf_agent_handle_call_list(bt_hf_info);
-       else
-               INFO("SCO Audio is already disconnected");
-
-       DBG("-");
-
-       return FALSE;
-}
-
 static gboolean __bt_hf_agent_sco_accept_cb(GIOChannel *chan, GIOCondition cond, gpointer user_data)
 {
        bt_hf_agent_info_t *bt_hf_info = user_data;
@@ -2374,7 +2577,10 @@ static gboolean __bt_hf_agent_sco_accept_cb(GIOChannel *chan, GIOCondition cond,
        g_io_channel_set_buffered(sco_io, FALSE);
 
        g_io_add_watch(sco_io, G_IO_HUP | G_IO_ERR | G_IO_NVAL,
-                                       __bt_hf_agent_sco_conn_cb, bt_hf_info);
+                                       __bt_hf_agent_sco_disconnect_cb, bt_hf_info);
+
+       if (bt_hf_info->state != BT_HF_STATE_CONNECTED)
+               ERR("HFP is not yet connected");
 
        /* S-Voice app requires the AudioConnected signal earlier */
        DBG("Emit AudioConnected Signal");
@@ -2397,12 +2603,12 @@ static gboolean __bt_hf_agent_sco_accept_cb(GIOChannel *chan, GIOCondition cond,
         * In the case of outgoing call we need to lauch the callapp.
         */
 
-       g_idle_add(__bt_agent_query_and_update_call_list, bt_hf_info);
+       __bt_hf_agent_launch_call_app();
 
        return TRUE;
 }
 
-void _bt_convert_addr_string_to_type_rev(unsigned char *addr,
+static void __bt_convert_addr_string_to_type_rev(unsigned char *addr,
                                        const char *address)
 {
        int i;
@@ -2411,7 +2617,7 @@ void _bt_convert_addr_string_to_type_rev(unsigned char *addr,
        ret_if(address == NULL);
        ret_if(addr == NULL);
 
-       for (i = 0; i < 6; i++) {
+       for (i = 0; i < BT_ADDRESS_LENGTH_MAX; i++) {
                addr[5 - i] = strtol(address, &ptr, 16);
                if (ptr[0] != '\0') {
                        if (ptr[0] != ':')
@@ -2429,9 +2635,6 @@ static gboolean __bt_hf_agent_sco_accept(bt_hf_agent_info_t *bt_hf_info)
        bdaddr_t bd_addr = {{0},};
        int sco_skt;
 
-       if (bt_hf_info->state != BT_HF_STATE_CONNECTED)
-               return FALSE;
-
        /* Create socket */
        sco_skt = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO);
        if (sco_skt < 0) {
@@ -2445,7 +2648,7 @@ static gboolean __bt_hf_agent_sco_accept(bt_hf_agent_info_t *bt_hf_info)
 
        DBG("Bind to address %s", bt_hf_info->remote_addr);
 
-       _bt_convert_addr_string_to_type_rev(bd_addr.b, bt_hf_info->remote_addr);
+       __bt_convert_addr_string_to_type_rev(bd_addr.b, bt_hf_info->remote_addr);
        memcpy(&addr.sco_bdaddr, &bd_addr, sizeof(bdaddr_t));
 
        if (bind(sco_skt, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
@@ -2581,11 +2784,9 @@ static gboolean __bt_establish_service_level_conn(bt_hf_agent_info_t *bt_hf_info
        gchar cmd_buf[BT_HF_CMD_BUF_SIZE] = {0};
        gboolean ret;
        char *buf_ptr;
-       char *stop;
        guint feature = BT_HF_FEATURE_EC_ANDOR_NR |
                        BT_HF_FEATURE_CALL_WAITING_AND_3WAY |
                        BT_HF_FEATURE_CLI_PRESENTATION |
-                       BT_HF_FEATURE_VOICE_RECOGNITION |
                        BT_HF_FEATURE_REMOTE_VOLUME_CONTROL |
                        BT_HF_FEATURE_ENHANCED_CALL_STATUS;
 
@@ -2602,11 +2803,7 @@ static gboolean __bt_establish_service_level_conn(bt_hf_agent_info_t *bt_hf_info
        if (buf_ptr == NULL)
                return FALSE;
 
-       buf_ptr = strstr(buf_ptr, "BRSF:");
-       bt_hf_info->ag_features = strtol(buf_ptr + 5, &stop, 10);
-
-
-       if (!ret || !bt_hf_info->ag_features)
+       if (!ret || sscanf(buf_ptr, "\r\n+BRSF:%5d", &bt_hf_info->ag_features) != 1)
                return FALSE;
        INFO("Gateway supported features are 0x%X", bt_hf_info->ag_features);
 
@@ -2653,8 +2850,26 @@ static gboolean __bt_establish_service_level_conn(bt_hf_agent_info_t *bt_hf_info
        } else
                bt_hf_info->hold_multiparty_features = 0;
 
+       if (bt_hf_info->ag_features & BT_AG_FEATURE_INBAND_RINGTONE)
+               bt_hf_info->inband_ringtone_support = TRUE;
+       else
+               bt_hf_info->inband_ringtone_support = FALSE;
+
        INFO("Service layer connection successfully established...!");
 
+       bt_hf_info->slc = TRUE;
+       send_flag = FALSE;
+       g_id = 0;
+       memset(global_buff, 0, sizeof(global_buff));
+       return TRUE;
+}
+
+static void __bt_establish_initialization(bt_hf_agent_info_t *bt_hf_info)
+{
+       gchar buf[BT_HF_DATA_BUF_SIZE];
+       gchar cmd_buf[BT_HF_CMD_BUF_SIZE] = {0};
+       gboolean ret;
+
        __bt_hf_send_and_read(bt_hf_info, BT_HF_CALLER_IDENT_ENABLE, buf,
                        sizeof(BT_HF_CALLER_IDENT_ENABLE) - 1);
        __bt_hf_send_and_read(bt_hf_info, BT_HF_CARRIER_FORMAT, buf,
@@ -2682,45 +2897,66 @@ static gboolean __bt_establish_service_level_conn(bt_hf_agent_info_t *bt_hf_info
        else
                ERR("BT_HF_XSAT sending failed");
 
-       /* send Bluetooth Samsung Support Feature cmd */
-       ret = __bt_hf_send_and_read(bt_hf_info, BT_HF_BSSF, buf,
-                                               sizeof(BT_HF_BSSF) - 1);
-       if (ret)
-               INFO("SLC completed with all commands");
-       else
-               ERR("BT_HF_BSSF sending failed");
+       if (TIZEN_PROFILE_WEARABLE) {
+               /* send Bluetooth Samsung Support Feature cmd */
+               ret = __bt_hf_send_and_read(bt_hf_info, BT_HF_BSSF, buf,
+                                                       sizeof(BT_HF_BSSF) - 1);
+
+               /* If we got a 'OK' reply, peer AG is samsung device.
+                * Otherwise, non-samsung device */
+               if (ret && strstr(buf, "OK"))
+                       bt_hf_info->is_companion_dev = TRUE;
+               else
+                       bt_hf_info->is_companion_dev = FALSE;
 
-       bt_hf_info->slc = TRUE;
-       send_flag = FALSE;
-       g_id = 0;
-       memset(global_buff, 0, sizeof(global_buff));
-       return TRUE;
+               if (ret)
+                       INFO("SLC completed with [%s] device",
+                               bt_hf_info->is_companion_dev ? "SS Companion" : "Other");
+               else
+                       ERR("BT_HF_BSSF sending failed");
+       }
 }
 
 static void __bt_hf_agent_sigterm_handler(int signo)
 {
-       ERR_C("***** Signal handler came with signal %d *****", signo);
        GDBusConnection *conn;
+       int i;
+
+       ERR_C("***** Signal handler came with signal %d *****", signo);
 
        conn = __bt_hf_get_gdbus_connection();
        if (!conn) {
-               ERR("Unable to get connection");
-               return;
+               ERR("Unable to get G-DBus connection");
+               goto done;
        }
+       INFO("Getting gdbus connection done");
 
        __bt_hf_agent_emit_signal(conn,
                        BT_HF_AGENT_OBJECT_PATH,
                        BT_HF_SERVICE_INTERFACE,
-                       "CallEnded", NULL);
-       DBG("CallEnded Signal done");
+                       "CallIdle", NULL);
+       INFO("CallEnded Signal done");
+
+       g_dbus_connection_flush(conn, NULL, NULL, NULL);
+       INFO("Flush g_dbus_connection");
+
+done:
        if (gmain_loop) {
                g_main_loop_quit(gmain_loop);
-               DBG("Exiting");
+               INFO("Exiting");
                gmain_loop = NULL;
        } else {
                INFO_C("Terminating HF agent");
                exit(0);
        }
+
+       if (signo == SIGTERM)
+               return;
+
+       for (i = 0; i < BT_HF_SIG_NUM; i++)
+               sigaction(bt_hf_sig_to_handle[i], &(bt_hf_sigoldact[i]), NULL);
+
+       raise(signo);
 }
 
 static void __bt_convert_addr_type_to_rev_string(char *address,
@@ -2752,6 +2988,8 @@ static gboolean __bt_agent_request_service_level_conn(gpointer data)
        DBG("+");
        memset(prev_cmd, 0, BT_HF_CMD_BUF_SIZE);
 
+       __bt_hf_agent_sco_accept(&bt_hf_info);
+
        if (!__bt_establish_service_level_conn(&bt_hf_info)) {
                ERR("Service Level Connection is fail");
 
@@ -2782,8 +3020,6 @@ static gboolean __bt_agent_request_service_level_conn(gpointer data)
 
        bt_hf_info.state = BT_HF_STATE_CONNECTED;
 
-       __bt_hf_agent_sco_accept(&bt_hf_info);
-
        __bt_hf_agent_start_watch(&bt_hf_info);
 
        remote_addr = bt_hf_info.remote_addr;
@@ -2813,8 +3049,8 @@ static gboolean __bt_agent_request_service_level_conn(gpointer data)
                        "Connected",
                        g_variant_new("(s)", remote_addr));
 
-       /* Request the call list and launch call app if required */
-       __bt_hf_agent_handle_call_list(&bt_hf_info);
+       /* Establish the initialization */
+       __bt_establish_initialization(&bt_hf_info);
 
 done:
        DBG("-");
@@ -2867,6 +3103,11 @@ static gboolean __bt_hf_agent_release(void)
        int bt_device_state = VCONFKEY_BT_DEVICE_NONE;
        GDBusConnection *conn;
 
+       if (clcc_timer) {
+               g_source_remove(clcc_timer);
+               clcc_timer = 0;
+       }
+
        if (bt_hf_info.state == BT_HF_STATE_DISCONNECTED) {
                ERR("hf is already disconnected");
                return FALSE;
@@ -2941,8 +3182,7 @@ static int __bt_hf_register_profile(const char *uuid, uint16_t version,
        GVariantBuilder *builder;
        gchar *path = NULL;
 
-       proxy = __bt_hf_gdbus_get_service_proxy(BLUEZ_SERVICE_NAME,
-                       "/org/bluez", BLUEZ_PROFILE_MGMT_INTERFACE);
+       proxy = __bt_hf_gdbus_get_profile_proxy();
 
        if (proxy == NULL)
                return BT_HF_AGENT_ERROR_INTERNAL;
@@ -3066,6 +3306,78 @@ static void __bt_hf_agent_filter_cb(GDBusConnection *connection,
        DBG("-");
 }
 
+static int __bt_hf_agent_get_adapter_path(GDBusConnection *conn, char *path)
+{
+       GError *err = NULL;
+       GDBusProxy *manager_proxy = NULL;
+       GVariant *result = NULL;
+       char *adapter_path = NULL;
+
+       if (conn == NULL)
+               return BT_HF_AGENT_ERROR_INTERNAL;
+
+       manager_proxy =  g_dbus_proxy_new_sync(conn,
+                       G_DBUS_PROXY_FLAGS_NONE, NULL,
+                       BLUEZ_SERVICE_NAME,
+                       "/",
+                       BT_MANAGER_INTERFACE,
+                       NULL, &err);
+
+       if (!manager_proxy) {
+               ERR("Unable to create proxy: %s", err->message);
+               goto fail;
+       }
+
+       result = g_dbus_proxy_call_sync(manager_proxy, "DefaultAdapter", NULL,
+                       G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
+       if (!result) {
+               if (err != NULL)
+                       ERR("Fail to get DefaultAdapter (Error: %s)", err->message);
+               else
+                       ERR("Fail to get DefaultAdapter");
+
+               goto fail;
+       }
+
+       if (g_strcmp0(g_variant_get_type_string(result), "(o)")) {
+               ERR("Incorrect result\n");
+               goto fail;
+       }
+
+       g_variant_get(result, "(&o)", &adapter_path);
+
+       if (adapter_path == NULL ||
+               strlen(adapter_path) >= BT_ADAPTER_OBJECT_PATH_MAX) {
+               ERR("Adapter path is inproper\n");
+               goto fail;
+       }
+
+       if (path)
+               g_strlcpy(path, adapter_path, BT_ADAPTER_OBJECT_PATH_MAX);
+
+       if (g_obj_path == NULL) {
+               g_obj_path = g_strdup(adapter_path);
+               INFO("Update g_obj_path [%s]", adapter_path);
+       }
+
+       g_variant_unref(result);
+       g_object_unref(manager_proxy);
+
+       return 0;
+
+fail:
+       g_clear_error(&err);
+
+       if (result)
+               g_variant_unref(result);
+
+       if (manager_proxy)
+               g_object_unref(manager_proxy);
+
+       return BT_HF_AGENT_ERROR_INTERNAL;
+
+}
+
 static void __bt_hf_agent_dbus_init(void)
 {
        GDBusConnection *conn;
@@ -3082,6 +3394,10 @@ static void __bt_hf_agent_dbus_init(void)
                return;
        }
 
+       if (!__bt_hf_agent_get_adapter_path(gdbus_conn , NULL)) {
+               __bt_hf_agent_register();
+       }
+
        interface_added_sig_id = g_dbus_connection_signal_subscribe(conn,
                                NULL, BT_MANAGER_INTERFACE, BT_INTERFACES_ADDED, NULL, NULL, 0,
                                __bt_hf_agent_filter_cb, NULL, NULL);
@@ -3091,15 +3407,13 @@ static void __bt_hf_agent_dbus_init(void)
                                __bt_hf_agent_filter_cb, NULL, NULL);
 
        DBG("-");
-       return;
 }
 
 static void __bt_hf_agent_dbus_deinit(void)
 {
-
-       if (service_gproxy) {
-               g_object_unref(service_gproxy);
-               service_gproxy = NULL;
+       if (profile_gproxy) {
+               g_object_unref(profile_gproxy);
+               profile_gproxy = NULL;
        }
 
        if (gdbus_conn) {
@@ -3117,7 +3431,6 @@ static void __bt_hf_agent_dbus_deinit(void)
                g_object_unref(gdbus_conn);
                gdbus_conn = NULL;
        }
-       return;
 }
 
 static int _hf_agent_answer_call(GDBusMethodInvocation *context)
@@ -3298,6 +3611,88 @@ static int _hf_agent_send_3way_cmd(GDBusMethodInvocation *context, char *cmd)
        return BT_HF_AGENT_ERROR_NONE;
 }
 
+static gboolean bt_hf_agent_sco_connect(void)
+{
+       struct sockaddr_sco addr;
+       bdaddr_t bd_addr = {{0},};
+       int sk;
+       GIOChannel *sco_io;
+       GDBusConnection *conn;
+
+       DBG("+");
+
+       if (bt_hf_info.state != BT_HF_STATE_CONNECTED) {
+               ERR("HF RFCOMM not Connected");
+               return FALSE;
+       }
+
+       if (bt_hf_info.cli_sco_fd > 0) {
+               ERR("SCO Already connected..");
+               return FALSE;
+       }
+
+       /* Create socket */
+       sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO);
+       if (sk < 0) {
+               ERR("Can't create SCO socket");
+               return FALSE;
+       }
+
+       /* Bind to local address */
+       memset(&addr, 0, sizeof(addr));
+       addr.sco_family = AF_BLUETOOTH;
+       memcpy(&addr.sco_bdaddr, &bd_addr, sizeof(bdaddr_t));
+
+       if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+               ERR("Can't bind socket");
+               goto error;
+       }
+
+       /* Connect to remote device */
+       memset(&addr, 0, sizeof(addr));
+       addr.sco_family = AF_BLUETOOTH;
+       __bt_convert_addr_string_to_type_rev(addr.sco_bdaddr.b, bt_hf_info.remote_addr);
+       if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+               ERR("Can't connect");
+               goto error;
+       }
+
+       DBG("SCO Connected");
+
+        bt_hf_info.cli_sco_fd = sk;
+
+       sco_io = g_io_channel_unix_new(sk);
+       g_io_channel_set_close_on_unref(sco_io, TRUE);
+       g_io_channel_set_encoding(sco_io, NULL, NULL);
+       g_io_channel_set_flags(sco_io, G_IO_FLAG_NONBLOCK, NULL);
+       g_io_channel_set_buffered(sco_io, FALSE);
+
+       g_io_add_watch(sco_io, G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+                                       __bt_hf_agent_sco_disconnect_cb, &bt_hf_info);
+
+       DBG("Emit AudioConnected Signal - Outgoing SCo connection");
+       sco_audio_connected = BT_HF_AUDIO_CONNECTED;
+
+       conn = __bt_hf_get_gdbus_connection();
+       if (!conn) {
+               ERR("Unable to get connection");
+               return FALSE;
+       }
+
+       __bt_hf_agent_emit_signal(conn,
+                       BT_HF_AGENT_OBJECT_PATH,
+                       BT_HF_SERVICE_INTERFACE,
+                       "AudioConnected", NULL);
+
+       DBG("-");
+       return TRUE;
+
+error:
+       close(sk);
+       DBG("-");
+       return FALSE;
+}
+
 static gboolean bt_hf_agent_sco_disconnect(void)
 {
        DBG("+");
@@ -3356,12 +3751,6 @@ static int bt_hf_agent_send_at_cmd(GDBusMethodInvocation *context, char *atcmd)
        if (bt_hf_info.state != BT_HF_STATE_CONNECTED)
                return  BT_HF_AGENT_ERROR_NOT_CONNECTED;
 
-       /* Should not send cmds if DUT has sent a command and waiting for response */
-       if (prev_cmd[0] != 0) {
-               INFO("DUT is waiting a respond for previous TX cmd. Skip sending.");
-               return BT_HF_AGENT_ERROR_INTERNAL;
-       }
-
        strncpy(cmd_buf, atcmd, sizeof(cmd_buf) - 2);
        strncat(cmd_buf, "\r", (sizeof(cmd_buf) - 1) - strlen(cmd_buf));
 
@@ -3380,7 +3769,6 @@ static uint32_t __bt_hf_agent_get_hf_features(void)
        uint32_t hf_features = BT_HF_FEATURE_EC_ANDOR_NR |
                        BT_HF_FEATURE_CALL_WAITING_AND_3WAY |
                        BT_HF_FEATURE_CLI_PRESENTATION |
-                       BT_HF_FEATURE_VOICE_RECOGNITION |
                        BT_HF_FEATURE_REMOTE_VOLUME_CONTROL |
                        BT_HF_FEATURE_ENHANCED_CALL_STATUS |
                        BT_HF_FEATURE_CODEC_NEGOTIATION;
@@ -3395,22 +3783,27 @@ static uint32_t __bt_hf_agent_get_hf_features(void)
 
 int main(void)
 {
+       int i;
        struct sigaction sa;
        uint32_t hf_features;
 
        INFO_C("### Starting Bluetooth HF agent");
 
+#if GLIB_VERSION_MIN_REQUIRED < GLIB_VERSION_2_36
+       g_type_init();
+#endif
        hf_features = __bt_hf_agent_get_hf_features();
        bt_hf_info.feature = (uint16_t) hf_features & 0x3F;
 
        memset(&sa, 0, sizeof(sa));
        sa.sa_flags = SA_NOCLDSTOP;
        sa.sa_handler = __bt_hf_agent_sigterm_handler;
-       sigaction(SIGTERM, &sa, NULL);
 
-       /* Temporarily, block the below signal for debugging */
-//     sigaction(SIGSEGV, &sa, NULL);
-//     sigaction(SIGABRT, &sa, NULL);
+       for (i = 0; i < BT_HF_SIG_NUM; i++)
+               sigaction(bt_hf_sig_to_handle[i], &sa, &(bt_hf_sigoldact[i]));
+
+       g_log_set_default_handler(__on_log_glib, NULL);
+
        gmain_loop = g_main_loop_new(NULL, FALSE);
 
        if (gmain_loop == NULL) {
@@ -3419,6 +3812,7 @@ int main(void)
        }
 
        __bt_hf_agent_dbus_init();
+
        g_main_loop_run(gmain_loop);
 
        __bt_hf_agent_dbus_deinit();
index a86a7f1..d544bae 100644 (file)
 #ifdef __cplusplus
 extern "C" {
 #endif
+#include <unistd.h>
+#include <dlog.h>
+#include <stdio.h>
+#include <signal.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <sys/socket.h>
 
 #undef LOG_TAG
 #define LOG_TAG "BLUETOOTH_HF_AGENT"
@@ -50,24 +59,24 @@ extern "C" {
 #define ERR_C(fmt, arg...) \
        SLOGI_IF(TRUE,  LOG_COLOR_RED" "fmt" "LOG_COLOR_RESET, ##arg)
 
-
-#include <unistd.h>
-#include <dlog.h>
-#include <stdio.h>
-#include <signal.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <sys/socket.h>
+#define retv_if(expr, val) \
+       do { \
+               if (expr) { \
+                       ERR("(%s) return", #expr); \
+                       return (val); \
+               } \
+       } while (0)
 
 #define BTPROTO_SCO    2
-
 #define BT_HF_DATA_BUF_SIZE 1024
 #define BT_HF_CMD_BUF_SIZE 32
 #define BT_HF_INDICATOR_DESCR_SIZE 20
 #define BT_HF_CALLER_NUM_SIZE 64       /* size of number + type */
 #define BT_HF_FMT_STR_SIZE 32
+#define BT_ADDRESS_LENGTH_MAX 6
+#define BT_ADAPTER_OBJECT_PATH_MAX 50
+#define AT_CMD_BUFF_SIZE 500
+#define BT_MAX_TEL_NUM_STR 100
 
 #define BT_HF_AGENT_ERROR (__bt_hf_agent_error_quark())
 
@@ -80,12 +89,105 @@ extern "C" {
 #define BT_ERROR_ALREADY_EXIST "AlreadyExists"
 #define BT_ERROR_ALREADY_CONNECTED "Already Connected"
 #define BT_ERROR_NO_MEMORY "No memory"
+#define BT_ERROR_NO_DATA "No data"
 #define BT_ERROR_I_O_ERROR "I/O error"
 #define BT_ERROR_OPERATION_NOT_AVAILABLE "Operation currently not available"
 #define BT_ERROR_OPERATION_NOT_ALLOWED "Operation not allowed"
 #define BT_ERROR_OPERATION_NOT_SUPPORTED "Operation not supported"
 #define BT_ERROR_INVALID_FILE_DESCRIPTOR "Invalid File Descriptor"
 
+#define BT_HF_OK_RESPONSE "\r\nOK\r\n"
+#define BT_HF_ERROR_RESPONSE "ERROR"
+#define BT_HF_SEC_ERROR_RESPONSE "SERR"
+
+/* dbus interfaces */
+#define BT_HF_SERVICE_NAME "org.bluez.hf_agent"
+#define BT_HF_AGENT_OBJECT_PATH "/org/bluez/handsfree_agent"
+#define BT_HF_SERVICE_INTERFACE "org.tizen.HfApp"
+#define BT_HF_BLUEZ_OBJECT_PATH "/org/tizen/handsfree"
+#define BT_HF_BLUEZ_INTERFACE  "org.bluez.HandsfreeAgent"
+#define BLUEZ_SERVICE_NAME "org.bluez"
+#define BLUEZ_HF_INTERFACE_NAME "org.bluez.HandsfreeGateway"
+#define BLUEZ_PROFILE_MGMT_INTERFACE "org.bluez.ProfileManager1"
+#define BT_MANAGER_INTERFACE "org.freedesktop.DBus.ObjectManager"
+#define BT_ADAPTER_INTERFACE   "org.bluez.Adapter1"
+
+#define BT_INTERFACES_ADDED "InterfacesAdded"
+#define BT_INTERFACES_REMOVED "InterfacesRemoved"
+
+/* Handsfree features */
+#define BT_HF_FEATURE_EC_ANDOR_NR                      0x0001
+#define BT_HF_FEATURE_CALL_WAITING_AND_3WAY    0x0002
+#define BT_HF_FEATURE_CLI_PRESENTATION         0x0004
+#define BT_HF_FEATURE_VOICE_RECOGNITION                0x0008
+#define BT_HF_FEATURE_REMOTE_VOLUME_CONTROL    0x0010
+#define BT_HF_FEATURE_ENHANCED_CALL_STATUS     0x0020
+#define BT_HF_FEATURE_ENHANCED_CALL_CONTROL    0x0040
+#define BT_HF_FEATURE_CODEC_NEGOTIATION                0x0080
+
+/* Audio Gateway features */
+#define BT_AG_FEATURE_3WAY     0x1
+#define BT_AG_FEATURE_NREC     0x0002
+#define BT_AG_FEATURE_VOICE_RECOGNITION        0x0004
+#define BT_AG_FEATURE_INBAND_RINGTONE  0x0008
+#define BT_AG_FEATURE_VOICE_TAG        0x0010
+#define BT_AG_FEATURE_REJECT_CALL      0x0020
+#define BT_AG_FEATURE_ENHANCED_CALL_STATUS     0x0040
+#define BT_AG_FEATURE_ENHANCED_CALL_CONTROL    0x0080
+#define BT_AG_FEATURE_EXTENDED_RES_CODE        0x100
+#define BT_AG_FEATURE_CODEC_NEGOTIATION        0x0200
+
+/* SCO Codec types */
+#define BT_HF_CODEC_ID_CVSD 1
+#define BT_HF_CODEC_ID_MSBC 2
+
+/* AT commands */
+#define BT_HF_FEATURES "AT+BRSF=%d\r"     /* = 0x7F = All features supported */
+#define BT_HF_INDICATORS_SUPP "AT+CIND=?\r"
+#define BT_HF_INDICATORS_VAL "AT+CIND?\r"
+#define BT_HF_INDICATORS_ENABLE "AT+CMER=3,0,0,1\r"
+#define BT_HF_HOLD_MPTY_SUPP "AT+CHLD=?\r"
+#define BT_HF_CALLER_IDENT_ENABLE "AT+CLIP=1\r"
+#define BT_HF_CARRIER_FORMAT "AT+COPS=3,0\r"
+#define BT_HF_EXTENDED_RESULT_CODE "AT+CMEE=1\r"
+#define BT_HF_INDICATORS_ACTIVATION "AT+BIA="
+#define BT_HF_ANSWER_CALL "ATA\r"
+#define BT_HF_END_CALL "AT+CHUP\r"
+#define BT_HF_REDIAL "AT+BLDN\r"
+#define BT_HF_DIAL_NO "ATD%.100s;\r"
+#define BT_HF_VOICE_RECOGNITION "AT+BVRA=%d\r"
+#define BT_HF_XSAT "AT+XSAT=00,TY,WA\r"
+#define BT_HF_BSSF "AT+BSSF=8\r"
+#define BT_HF_CALLLIST "AT+CLCC\r"
+#define BT_HF_AVAILABLE_CODEC "AT+BAC=%d,%d\r"
+#define BT_HF_CODEC_SELECT "AT+BCS=%d\r"
+#define BT_HF_SPEAKER_GAIN "AT+VGS=%d\r"
+#define BT_HF_DTMF "AT+VTS=%s\r"
+#define BT_HF_NREC "AT+NREC=0\r"
+#define BT_HF_CALLWAIT_NOTI_ENABLE "AT+CCWA=1\r"
+#define BT_HF_RELEASE_ALL "AT+CHLD=0\r"
+#define BT_HF_RELEASE_AND_ACCEPT "AT+CHLD=1\r"
+#define BT_HF_ACCEPT_AND_HOLD "AT+CHLD=2\r"
+#define BT_HF_JOIN_CALL "AT+CHLD=3\r"
+
+#define BT_HF_MAX_SPEAKER_GAIN 15
+#define BT_HF_MIN_SPEAKER_GAIN 0
+
+/* Hold and multipary services on AG */
+#define BT_HF_CHLD_0   0x01 /* Releases all held calls or sets User Busy for a waiting call */
+#define BT_HF_CHLD_1   0x02 /* Releases all active calls and accept others */
+#define BT_HF_CHLD_1x  0x04 /* Releases specified active call only (<idx>) */
+#define BT_HF_CHLD_2   0x08 /* Places all active calls on hold and accepts others */
+#define BT_HF_CHLD_2x  0x10 /* Place all calls on hold EXCEPT the call indicated by <idx> */
+#define BT_HF_CHLD_3   0x20 /* Adds a held call to the conversation */
+#define BT_HF_CHLD_4   0x40 /* Explicit Call Transfer */
+
+enum hfp_version {
+       HFP_VERSION_1_5 = 0x0105,
+       HFP_VERSION_1_6 = 0x0106,
+       HFP_VERSION_LATEST = HFP_VERSION_1_6,
+};
+
 typedef enum {
        BT_HF_AGENT_ERROR_NONE,
        BT_HF_AGENT_ERROR_INTERNAL,
@@ -97,6 +199,7 @@ typedef enum {
        BT_HF_AGENT_ERROR_ALREADY_EXIST,
        BT_HF_AGENT_ERROR_ALREADY_CONNECTED,
        BT_HF_AGENT_ERROR_NO_MEMORY,
+       BT_HF_AGENT_ERROR_NO_DATA,
        BT_HF_AGENT_ERROR_I_O_ERROR,
        BT_HF_AGENT_ERROR_APPLICATION,
        BT_HF_AGENT_ERROR_NOT_ALLOWED,
@@ -133,11 +236,20 @@ typedef enum {
 } bt_ag_cme_error_t;
 
 typedef enum {
+       BT_HF_STATE_DISCONNECTED,
+       BT_HF_STATE_CONNECTED
+} bt_hf_state_t;
+
+typedef enum {
+       BT_HF_AUDIO_DISCONNECTED,
+       BT_HF_AUDIO_CONNECTED
+} bt_hf_sco_state_t;
+
+typedef enum {
        BT_HF_CALL_DIR_OUTGOING,
        BT_HF_CALL_DIR_INCOMING,
 } bt_hf_call_direction_t;
 
-/* Call status as per spec */
 typedef enum {
        BT_HF_CALL_STAT_ACTIVE,
        BT_HF_CALL_STAT_HELD,
@@ -147,137 +259,6 @@ typedef enum {
        BT_HF_CALL_STAT_WAITING,
 } bt_hf_call_status_t;
 
-enum hfp_version {
-       HFP_VERSION_1_5 = 0x0105,
-       HFP_VERSION_1_6 = 0x0106,
-       HFP_VERSION_LATEST = HFP_VERSION_1_6,
-};
-
-/*Handsfree supported features*/
-#define BT_HF_FEATURE_EC_ANDOR_NR                      0x0001
-#define BT_HF_FEATURE_CALL_WAITING_AND_3WAY    0x0002
-#define BT_HF_FEATURE_CLI_PRESENTATION         0x0004
-#define BT_HF_FEATURE_VOICE_RECOGNITION                0x0008
-#define BT_HF_FEATURE_REMOTE_VOLUME_CONTROL    0x0010
-#define BT_HF_FEATURE_ENHANCED_CALL_STATUS     0x0020
-#define BT_HF_FEATURE_ENHANCED_CALL_CONTROL    0x0040
-#define BT_HF_FEATURE_CODEC_NEGOTIATION                0x0080
-
-/*AG suported feature*/
-#define BT_AG_FEATURE_3WAY 0x1
-#define BT_AG_FEATURE_NREC     0x0002
-#define BT_AG_FEATURE_EXTENDED_RES_CODE 0x100
-#define BT_AG_FEATURE_CODEC_NEGOTIATION        0x0200
-
-#define BT_HF_CODEC_ID_CVSD 1
-#define BT_HF_CODEC_ID_MSBC 2
-
-#define BT_HF_AUDIO_DISCONNECTED 0
-#define BT_HF_AUDIO_CONNECTED 1
-
-#define BT_MAX_TEL_NUM_STR 100
-
-#define BT_HF_FEATURES "AT+BRSF=%d\r"     /* = 0x7F = All features supported */
-#define BT_HF_INDICATORS_SUPP "AT+CIND=?\r"
-#define BT_HF_INDICATORS_VAL "AT+CIND?\r"
-#define BT_HF_INDICATORS_ENABLE "AT+CMER=3,0,0,1\r"
-#define BT_HF_HOLD_MPTY_SUPP "AT+CHLD=?\r"
-#define BT_HF_CALLER_IDENT_ENABLE "AT+CLIP=1\r"
-#define BT_HF_CARRIER_FORMAT "AT+COPS=3,0\r"
-#define BT_HF_EXTENDED_RESULT_CODE "AT+CMEE=1\r"
-#define BT_HF_INDICATORS_ACTIVATION "AT+BIA="
-#define BT_HF_ANSWER_CALL "ATA\r"
-#define BT_HF_END_CALL "AT+CHUP\r"
-#define BT_HF_REDIAL "AT+BLDN\r"
-#define BT_HF_DIAL_NO "ATD%.100s;\r"
-#define BT_HF_VOICE_RECOGNITION "AT+BVRA=%d\r"
-#define BT_HF_XSAT "AT+XSAT=00,TY,WA\r"
-#define BT_HF_BSSF "AT+BSSF=8\r"
-#define BT_HF_CALLLIST "AT+CLCC\r"
-#define BT_HF_AVAILABLE_CODEC "AT+BAC=%d,%d\r"
-#define BT_HF_CODEC_SELECT "AT+BCS=%d\r"
-#define BT_HF_SPEAKER_GAIN "AT+VGS=%d\r"
-#define BT_HF_DTMF "AT+VTS=%s\r"
-#define BT_HF_NREC "AT+NREC=0\r"
-#define BT_HF_CALLWAIT_NOTI_ENABLE "AT+CCWA=1\r"
-#define BT_HF_RELEASE_ALL "AT+CHLD=0\r"
-#define BT_HF_RELEASE_AND_ACCEPT "AT+CHLD=1\r"
-#define BT_HF_ACCEPT_AND_HOLD "AT+CHLD=2\r"
-#define BT_HF_JOIN_CALL "AT+CHLD=3\r"
-
-#define BT_MAX_EVENT_STR_LENGTH         50
-#define BT_AGENT_SYSPOPUP_TIMEOUT_FOR_MULTIPLE_POPUPS 200
-
-#define BT_HF_MAX_SPEAKER_GAIN 15
-#define BT_HF_MIN_SPEAKER_GAIN 0
-
-
-typedef enum {
-       BT_AGENT_EVENT_HANDSFREE_CONNECT = 0x1100,
-       BT_AGENT_EVENT_HANDSFREE_DISCONNECT = 0x1200,
-} bt_hfp_agent_event_type_t;
-
-/* Hold and multipary AG features.
- * Comments below are copied from hands-free spec for reference */
-/* Releases all held calls or sets User Determined User Busy (UDUB)
- * for a waiting call */
-#define BT_HF_CHLD_0 0x01
-/* Releases all active calls (if any exist) and accepts the other
- * (held or waiting) call */
-#define BT_HF_CHLD_1 0x02
-/* Releases specified active call only <x> */
-#define BT_HF_CHLD_1x 0x04
-/* Places all active calls (if any exist) on hold and accepts the other
- * (held or waiting) call */
-#define BT_HF_CHLD_2 0x08
-/* Request private consultation mode with specified call <x> (Place all
- * calls on hold EXCEPT the call <x>) */
-#define BT_HF_CHLD_2x 0x10
-/* Adds a held call to the conversation */
-#define BT_HF_CHLD_3 0x20
-/* Connects the two calls and disconnects the subscriber from both calls
- * (Explicit Call Transfer). Support for this value and its associated
- * functionality is optional for the HF. */
-#define BT_HF_CHLD_4 0x40
-
-#define BT_HF_OK_RESPONSE "\r\nOK\r\n"
-#define BT_HF_ERROR_RESPONSE "ERROR"
-#define BT_HF_SEC_ERROR_RESPONSE "SERR"
-
-#define BT_HF_SERVICE_NAME "org.bluez.hf_agent"
-#define BT_HF_AGENT_OBJECT_PATH "/org/bluez/handsfree_agent"
-#define BT_HF_SERVICE_INTERFACE "org.tizen.HfApp"
-
-#define BT_HF_BLUEZ_OBJECT_PATH "/org/tizen/handsfree"
-#define BT_HF_BLUEZ_INTERFACE  "org.bluez.HandsfreeAgent"
-
-#define BLUEZ_SERVICE_NAME "org.bluez"
-#define BLUEZ_HF_INTERFACE_NAME "org.bluez.HandsfreeGateway"
-
-#define PM_SERVICE_NAME "org.tizen.system.deviced"
-#define PM_OBJECT_PATH "/Org/Tizen/System/DeviceD/Display"
-#define PM_INTERFACE_NAME "org.tizen.system.deviced.display"
-#define AT_CMD_BUFF_SIZE 500
-#define BLUEZ_PROFILE_MGMT_INTERFACE "org.bluez.ProfileManager1"
-#define BT_MANAGER_INTERFACE "org.freedesktop.DBus.ObjectManager"
-#define BT_ADAPTER_INTERFACE   "org.bluez.Adapter1"
-
-#define BT_INTERFACES_ADDED "InterfacesAdded"
-#define BT_INTERFACES_REMOVED "InterfacesRemoved"
-
-#define retv_if(expr, val) \
-       do { \
-               if (expr) { \
-                       ERR("(%s) return", #expr); \
-                       return (val); \
-               } \
-       } while (0)
-
-typedef enum {
-       BT_HF_STATE_DISCONNECTED,
-       BT_HF_STATE_CONNECTED
-} bt_hf_state_t;
-
 typedef struct {
        guint32 fd;
        gint sco_fd;
@@ -297,6 +278,8 @@ typedef struct {
 
        gboolean is_dialing;
        gboolean call_active;
+       gboolean inband_ringtone_support;
+       gboolean is_companion_dev;
 
        guint ciev_call_status;
        guint ciev_call_setup_status;
@@ -321,10 +304,10 @@ typedef struct {
        int timer_id;
 } bt_hf_agent_send_at_info;
 
-struct hf_event {
+typedef struct  {
        const char *cmd;
        int (*callback) (bt_hf_agent_info_t *bt_hf_info, const char *buf);
-};
+} bt_hf_event;
 
 typedef struct {
        unsigned char b[6];