Merge branch 'master' into tizen_2.1
[platform/core/connectivity/bluetooth-agent.git] / hfp-agent / bluetooth-hfp-agent.c
1 /*
2  * bluetooth-agent
3  *
4  * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *              http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <unistd.h>
23 #include <glib.h>
24 #include <dbus/dbus-glib.h>
25 #include <dbus/dbus.h>
26 #include <dbus/dbus-glib-lowlevel.h>
27 #include <signal.h>
28
29 #include <TapiUtility.h>
30 #include <ITapiSim.h>
31 #include <app.h>
32 #include <aul.h>
33
34 #include "vconf.h"
35 #include "vconf-keys.h"
36 #include "contacts.h"
37 #include "appsvc.h"
38
39 #include "bluetooth-hfp-agent.h"
40
41 static GMainLoop *gmain_loop = NULL;
42 static DBusGConnection *g_connection = NULL;
43 static DBusConnection *gconn = NULL;
44 static gboolean nrec_status = FALSE;
45
46 #define BT_ERROR_INTERNAL "InternalError"
47 #define BT_ERROR_NOT_AVAILABLE "NotAvailable"
48 #define BT_ERROR_NOT_CONNECTED "NotConnected"
49 #define BT_ERROR_BUSY "InProgress"
50 #define BT_ERROR_INVALID_PARAM "InvalidArguments"
51 #define BT_ERROR_ALREADY_EXSIST "AlreadyExists"
52 #define BT_ERROR_ALREADY_CONNECTED "Already Connected"
53 #define BT_ERROR_NO_MEMORY "No memory"
54 #define BT_ERROR_I_O_ERROR "I/O error"
55 #define BT_ERROR_OPERATION_NOT_AVAILABLE "Operation currently not available"
56 #define BT_ERROR_BATTERY "Battery error "
57 #define BT_ERROR_SIGNAL "Signal error"
58 #define BT_ERROR_NO_CALL_LOG "No Call log"
59 #define BT_ERROR_INVLAID_DTMF "Invalid dtmf"
60
61 #define BLUEZ_SERVICE_NAME "org.bluez"
62 #define TELEPHONY_CSD_INTERFACE "org.tizen.telephony.csd"
63 #define TELEPHONY_CSD_OBJECT_PATH "/org/tizen/csd"
64 #define TELEPHONY_APP_INTERFACE "org.tizen.csd.Call.Instance"
65
66 #define BT_HFP_AGENT_SET_PROPERTY "SetProperty"
67
68 #define BT_HFP_AGENT_OBJECT "/org/bluez/agent/hfp_agent"
69 #define BT_HFP_AGENT_INTERFACE "org.bluez.hfp_agent"
70
71 #define BT_SIGNAL_ARRAY_MAX 2
72
73 /* AT+CSQ : Returns received signal strength indication.
74      Command response: +CSQ: <rssi>,<ber>
75     <ber> is not supported and has a constant value of 99, included for compatibility reasons.
76 */
77 #define BT_SIGNAL_QUALITY_BER 99
78
79 /*Length of the string used to send telephone number to app-svc
80    format: tel:<number>
81 */
82 #define BT_MAX_TEL_NUM_STRING 20
83
84 /**
85  * @brief Outgoing call type status
86  *
87  * 0 : Follow last call log \n
88  * 1 : Voice call \n
89  * 2 : Video call \n
90  */
91 #define BT_FOLLOW_CALL_LOG 0
92 #define BT_VOICE_CALL 1
93 #define BT_VIDEO_CALL 2
94
95 /**
96  * @brief The status of making outgoing calls with BT headsets
97  *
98  * 0 : Even when device locked \n
99  * 1 : Only when device unlocked \n
100  */
101 #define BT_MO_EVEN_LOCKED 0
102 #define BT_MO_ONLY_UNLOCKED 1
103
104 typedef struct {
105         GObject parent;
106 } BtHfpAgent;
107
108 typedef struct {
109         GObjectClass parent;
110 } BtHfpAgentClass;
111
112 GType bt_hfp_agent_get_type(void);
113
114 #define BT_HFP_TYPE_AGENT (bt_hfp_agent_get_type())
115
116 #define BT_HFP_AGENT(object)(G_TYPE_CHECK_INSTANCE_CAST((object), \
117                         BT_HFP_TYPE_AGENT , BtHfpAgent))
118
119 #define BT_HFP_AGENT_CLASS(klass)(G_TYPE_CHECK_CLASS_CAST((klass), \
120                         BT_HFP_TYPE_AGENT , BtHfpAgentClass))
121
122 #define BT_IS_HFP_AGENT(object)(G_TYPE_CHECK_INSTANCE_TYPE((object), \
123                         BT_HFP_TYPE_AGENT))
124
125 #define BT_IS_HFP_AGENT_CLASS(klass)(G_TYPE_CHECK_CLASS_TYPE((klass), \
126                         BT_HFP_TYPE_AGENT))
127
128 #define BT_HFP_AGENT_GET_CLASS(obj)(G_TYPE_INSTANCE_GET_CLASS((obj), \
129                         BT_HFP_TYPE_AGENT , BtHfpAgentClass))
130
131 G_DEFINE_TYPE(BtHfpAgent, bt_hfp_agent, G_TYPE_OBJECT)
132
133 static gboolean bt_hfp_agent_register_application(BtHfpAgent *agent,
134                                 const gchar *path, DBusGMethodInvocation *context);
135
136 static gboolean bt_hfp_agent_unregister_application(BtHfpAgent *agent,
137                                 const gchar *path, DBusGMethodInvocation *context);
138
139 static gboolean bt_hfp_agent_incoming_call(BtHfpAgent *agent, const gchar *path,
140                                 const gchar *number, gint call_id,
141                                 DBusGMethodInvocation *context);
142
143 static gboolean bt_hfp_agent_outgoing_call(BtHfpAgent *agent, const gchar *path,
144                                 const gchar *number, gint call_id,
145                                 DBusGMethodInvocation *context);
146
147 static gboolean bt_hfp_agent_change_call_status(BtHfpAgent *agent,
148                                 const gchar *path, gint status, gint call_id,
149                                 DBusGMethodInvocation *context);
150
151 static gboolean bt_hfp_agent_answer_call(BtHfpAgent *agent, unsigned int call_id,
152                                 const gchar *path, const gchar *sender,
153                                 DBusGMethodInvocation *context);
154
155 static gboolean bt_hfp_agent_release_call(BtHfpAgent *agent, unsigned int call_id,
156                                 const gchar *path, const gchar *sender,
157                                 DBusGMethodInvocation *context);
158
159 static gboolean bt_hfp_agent_reject_call(BtHfpAgent *agent, unsigned int call_id,
160                                 const gchar *path, const gchar *sender,
161                                 DBusGMethodInvocation *context);
162
163 static gboolean bt_hfp_agent_threeway_call(BtHfpAgent *agent, gint call_id,
164                                 const gchar *path, const gchar *sender,
165                                 DBusGMethodInvocation *context);
166
167 static gboolean bt_hfp_agent_dial_last_num(BtHfpAgent *agent,
168                                 DBusGMethodInvocation *context);
169
170 static gboolean bt_hfp_agent_dial_num(BtHfpAgent *agent,
171                                 const gchar *number, guint flags,
172                                 DBusGMethodInvocation *context);
173
174 static gboolean bt_hfp_agent_dial_memory(BtHfpAgent *agent, gint location,
175                                 DBusGMethodInvocation *context);
176
177 static gboolean bt_hfp_agent_send_dtmf(BtHfpAgent *agent, const gchar *dtmf,
178                                 const gchar *path, const gchar *sender,
179                                 DBusGMethodInvocation *context);
180
181 static gboolean bt_hfp_agent_voice_dial(BtHfpAgent *agent, gboolean activate,
182                                 DBusGMethodInvocation *context);
183
184 static gboolean bt_hfp_agent_get_battery_status(BtHfpAgent *object,
185                                 DBusGMethodInvocation *context);
186
187 static gboolean bt_hfp_agent_get_signal_quality(BtHfpAgent *object,
188                                 DBusGMethodInvocation *context);
189
190 static gboolean bt_hfp_agent_get_properties(BtHfpAgent *agent,
191                                 DBusGMethodInvocation *context);
192
193 static gboolean bt_hfp_agent_get_operator_name(BtHfpAgent *object,
194                                 DBusGMethodInvocation *context);
195
196 static gboolean bt_hfp_agent_nrec_status(BtHfpAgent *agent, gboolean status,
197                                 DBusGMethodInvocation *context);
198
199 #include "bluetooth_hfp_agent_glue.h"
200
201 static void bt_hfp_agent_init(BtHfpAgent *obj)
202 {
203         DBG("+\n");
204
205         g_assert(obj != NULL);
206 }
207
208 static void bt_hfp_agent_finalize(GObject *obj)
209 {
210         DBG("+\n");
211
212         G_OBJECT_CLASS(bt_hfp_agent_parent_class)->finalize(obj);
213 }
214
215 static void bt_hfp_agent_class_init(BtHfpAgentClass *klass)
216 {
217         DBG("+\n");
218
219         GObjectClass *object_class = (GObjectClass *)klass;
220
221         g_assert(klass != NULL);
222
223         object_class->finalize = bt_hfp_agent_finalize;
224
225         dbus_g_object_type_install_info(BT_HFP_TYPE_AGENT,
226                                         &dbus_glib_bt_hfp_agent_object_info);
227 }
228
229 static GQuark __bt_hfp_agent_error_quark(void)
230 {
231         DBG("+\n");
232
233         static GQuark quark = 0;
234         if (!quark)
235                 quark = g_quark_from_static_string("agent");
236
237         return quark;
238 }
239
240 static GError *__bt_hfp_agent_set_error(bt_hfp_agent_error_t error)
241 {
242         DBG("+\n");
243
244         switch (error) {
245         case BT_HFP_AGENT_ERROR_NOT_AVAILABLE:
246                 return g_error_new(BT_HFP_AGENT_ERROR, error,
247                                                 BT_ERROR_NOT_AVAILABLE);
248         case BT_HFP_AGENT_ERROR_NOT_CONNECTED:
249                 return g_error_new(BT_HFP_AGENT_ERROR, error,
250                                                 BT_ERROR_NOT_CONNECTED);
251         case BT_HFP_AGENT_ERROR_BUSY:
252                 return g_error_new(BT_HFP_AGENT_ERROR, error,
253                                                 BT_ERROR_BUSY);
254         case BT_HFP_AGENT_ERROR_INVALID_PARAM:
255                 return g_error_new(BT_HFP_AGENT_ERROR, error,
256                                                 BT_ERROR_INVALID_PARAM);
257         case BT_HFP_AGENT_ERROR_ALREADY_EXSIST:
258                 return g_error_new(BT_HFP_AGENT_ERROR, error,
259                                                 BT_ERROR_ALREADY_EXSIST);
260         case BT_HFP_AGENT_ERROR_ALREADY_CONNECTED:
261                 return g_error_new(BT_HFP_AGENT_ERROR, error,
262                                                 BT_ERROR_ALREADY_CONNECTED);
263         case BT_HFP_AGENT_ERROR_NO_MEMORY:
264                 return g_error_new(BT_HFP_AGENT_ERROR, error,
265                                                 BT_ERROR_NO_MEMORY);
266         case BT_HFP_AGENT_ERROR_I_O_ERROR:
267                 return g_error_new(BT_HFP_AGENT_ERROR, error,
268                                                 BT_ERROR_I_O_ERROR);
269         case BT_HFP_AGENT_ERROR_OPERATION_NOT_AVAILABLE:
270                 return g_error_new(BT_HFP_AGENT_ERROR, error,
271                                         BT_ERROR_OPERATION_NOT_AVAILABLE);
272         case BT_HFP_AGENT_ERROR_BATTERY_STATUS:
273                 return g_error_new(BT_HFP_AGENT_ERROR, error,
274                                         BT_ERROR_BATTERY);
275         case BT_HFP_AGENT_ERROR_SIGNAL_STATUS:
276                 return g_error_new(BT_HFP_AGENT_ERROR, error,
277                                         BT_ERROR_SIGNAL);
278         case BT_HFP_AGENT_ERROR_NO_CALL_LOGS:
279                 return g_error_new(BT_HFP_AGENT_ERROR, error,
280                                         BT_ERROR_NO_CALL_LOG);
281         case BT_HFP_AGENT_ERROR_INTERNAL:
282         default:
283                 return g_error_new(BT_HFP_AGENT_ERROR, error,
284                                                 BT_ERROR_INTERNAL);
285         }
286 }
287
288 static int __bt_hfp_agent_get_error(const char *error_message)
289 {
290         if (error_message == NULL) {
291                 DBG("Error message NULL\n");
292                 return BT_HFP_AGENT_ERROR_INTERNAL;
293         }
294
295         DBG("Error message = %s \n", error_message);
296
297         if (g_strcmp0(error_message, BT_ERROR_NOT_AVAILABLE) == 0)
298                 return BT_HFP_AGENT_ERROR_NOT_AVAILABLE;
299         else if (g_strcmp0(error_message, BT_ERROR_NOT_CONNECTED) == 0)
300                 return BT_HFP_AGENT_ERROR_NOT_CONNECTED;
301         else if (g_strcmp0(error_message, BT_ERROR_BUSY) == 0)
302                 return BT_HFP_AGENT_ERROR_BUSY;
303         else if (g_strcmp0(error_message, BT_ERROR_INVALID_PARAM) == 0)
304                 return BT_HFP_AGENT_ERROR_INVALID_PARAM;
305         else if (g_strcmp0(error_message, BT_ERROR_ALREADY_EXSIST) == 0)
306                 return BT_HFP_AGENT_ERROR_ALREADY_EXSIST;
307         else if (g_strcmp0(error_message, BT_ERROR_ALREADY_CONNECTED) == 0)
308                 return BT_HFP_AGENT_ERROR_ALREADY_CONNECTED;
309         else if (g_strcmp0(error_message, BT_ERROR_NO_MEMORY) == 0)
310                 return BT_HFP_AGENT_ERROR_NO_MEMORY;
311         else if (g_strcmp0(error_message, BT_ERROR_I_O_ERROR) == 0)
312                 return BT_HFP_AGENT_ERROR_I_O_ERROR;
313         else if (g_strcmp0(error_message,
314                                 BT_ERROR_OPERATION_NOT_AVAILABLE) == 0)
315                 return BT_HFP_AGENT_ERROR_OPERATION_NOT_AVAILABLE;
316         else if (g_strcmp0(error_message, BT_ERROR_INVLAID_DTMF) == 0)
317                 return BT_HFP_AGENT_ERROR_INVALID_DTMF;
318         else
319                 return BT_HFP_AGENT_ERROR_INTERNAL;
320 }
321
322 static int __bt_hfp_agent_dbus_method_send(const char *service,
323                                 const char *path, const char *interface,
324                                 const char *method, gboolean response,
325                                 int type, ...)
326 {
327         DBusMessage *msg;
328         DBusMessage *reply;
329         DBusError err;
330         va_list args;
331         int error;
332
333         DBG("__bt_hfp_agent_dbus_method_send +\n");
334
335         msg = dbus_message_new_method_call(service, path, interface,
336                                                                 method);
337         if (!msg) {
338                 DBG("Unable to allocate new D-Bus %s message \n", method);
339                 return BT_HFP_AGENT_ERROR_INTERNAL;
340         }
341
342         va_start(args, type);
343
344         if (!dbus_message_append_args_valist(msg, type, args)) {
345                 dbus_message_unref(msg);
346                 va_end(args);
347                 return BT_HFP_AGENT_ERROR_INTERNAL;
348         }
349
350         va_end(args);
351
352         dbus_error_init(&err);
353
354         if (response) {
355                 reply = dbus_connection_send_with_reply_and_block(gconn,
356                                                         msg, -1, &err);
357                 dbus_message_unref(msg);
358
359                 if (!reply) {
360                         DBG("Error returned in method call\n");
361                         if (dbus_error_is_set(&err)) {
362                                 error = __bt_hfp_agent_get_error(err.message);
363                                 dbus_error_free(&err);
364                                 return error;
365                         } else {
366                                 DBG("Error is not set\n");
367                                 return BT_HFP_AGENT_ERROR_INTERNAL;
368                         }
369                 }
370                 dbus_message_unref(reply);
371         } else {
372                 dbus_connection_send(gconn, msg, NULL);
373                 dbus_message_unref(msg);
374         }
375
376         DBG("__bt_hfp_agent_dbus_method_send -\n");
377
378         return BT_HFP_AGENT_ERROR_NONE;
379 }
380
381 static gboolean bt_hfp_agent_register_application(BtHfpAgent *agent,
382                                 const gchar *path, DBusGMethodInvocation *context)
383 {
384         gboolean flag = TRUE;
385         char *sender;
386         GError *error;
387         int ret;
388
389         DBG("bt_hfp_agent_register_application + \n");
390
391         if (path == NULL) {
392                 DBG("Invalid Argument path\n");
393                 error = __bt_hfp_agent_set_error(
394                                         BT_HFP_AGENT_ERROR_INVALID_PARAM);
395                 dbus_g_method_return_error(context, error);
396                 g_error_free(error);
397                 return FALSE;
398         }
399
400         DBG("Application path = %s\n", path);
401
402         sender = dbus_g_method_get_sender(context);
403
404         DBG("Sender = %s\n", sender);
405
406         ret = __bt_hfp_agent_dbus_method_send(BLUEZ_SERVICE_NAME,
407                                 TELEPHONY_CSD_OBJECT_PATH,
408                                 TELEPHONY_CSD_INTERFACE,
409                                 "RegisterTelephonyAgent", TRUE,
410                                 DBUS_TYPE_BOOLEAN, &flag,
411                                 DBUS_TYPE_STRING, &path,
412                                 DBUS_TYPE_STRING, &sender, DBUS_TYPE_INVALID);
413         g_free(sender);
414
415         if (ret != BT_HFP_AGENT_ERROR_NONE) {
416                 error = __bt_hfp_agent_set_error(ret);
417                 dbus_g_method_return_error(context, error);
418                 g_error_free(error);
419                 return FALSE;
420         }
421
422         dbus_g_method_return(context);
423
424         DBG("bt_hfp_agent_register_application - \n");
425         return TRUE;
426 }
427
428 static gboolean bt_hfp_agent_unregister_application(BtHfpAgent *agent,
429                                 const gchar *path, DBusGMethodInvocation *context)
430 {
431         gboolean flag = FALSE;
432         char *sender;
433         GError *error;
434         int ret;
435
436         DBG("bt_hfp_agent_unregister_application + \n");
437
438         if (path == NULL) {
439                 DBG("Invalid Argument path\n");
440                 error = __bt_hfp_agent_set_error(
441                                         BT_HFP_AGENT_ERROR_INVALID_PARAM);
442                 dbus_g_method_return_error(context, error);
443                 g_error_free(error);
444                 return FALSE;
445         }
446
447         DBG("Application path = %s \n", path);
448
449         sender = dbus_g_method_get_sender(context);
450
451         DBG("Sender = %s\n", sender);
452
453         ret = __bt_hfp_agent_dbus_method_send(BLUEZ_SERVICE_NAME,
454                                 TELEPHONY_CSD_OBJECT_PATH,
455                                 TELEPHONY_CSD_INTERFACE,
456                                 "RegisterTelephonyAgent", TRUE,
457                                 DBUS_TYPE_BOOLEAN, &flag,
458                                 DBUS_TYPE_STRING, &path,
459                                 DBUS_TYPE_STRING, &sender, DBUS_TYPE_INVALID);
460         g_free(sender);
461
462         if (ret != BT_HFP_AGENT_ERROR_NONE) {
463                 error = __bt_hfp_agent_set_error(ret);
464                 dbus_g_method_return_error(context, error);
465                 g_error_free(error);
466                 return FALSE;
467         }
468
469         dbus_g_method_return(context);
470
471         DBG("bt_hfp_agent_unregister_application - \n");
472         return TRUE;
473 }
474
475 static gboolean bt_hfp_agent_incoming_call(BtHfpAgent *agent, const gchar *path,
476                                 const gchar *number, gint call_id,
477                                 DBusGMethodInvocation *context)
478 {
479         GError *error;
480         char *sender;
481         int ret;
482
483         DBG("bt_hfp_agent_incoming_call + \n");
484
485         if (path == NULL || number == NULL) {
486                 DBG("Invalid Arguments\n");
487                 error = __bt_hfp_agent_set_error(
488                                         BT_HFP_AGENT_ERROR_INVALID_PARAM);
489                 dbus_g_method_return_error(context, error);
490                 g_error_free(error);
491                 return FALSE;
492         }
493
494         DBG("Application path = %s\n", path);
495         DBG("Phone number = %s\n", number);
496         DBG("Call id = %d\n", call_id);
497
498         sender = dbus_g_method_get_sender(context);
499
500         DBG("Sender = %s\n", sender);
501
502         ret = __bt_hfp_agent_dbus_method_send(BLUEZ_SERVICE_NAME,
503                                 TELEPHONY_CSD_OBJECT_PATH,
504                                 TELEPHONY_CSD_INTERFACE,
505                                 "Incoming", TRUE,
506                                 DBUS_TYPE_STRING, &path,
507                                 DBUS_TYPE_STRING, &number,
508                                 DBUS_TYPE_UINT32, &call_id,
509                                 DBUS_TYPE_STRING, &sender,
510                                 DBUS_TYPE_INVALID);
511         g_free(sender);
512
513         if (ret != BT_HFP_AGENT_ERROR_NONE) {
514                 error = __bt_hfp_agent_set_error(ret);
515                 dbus_g_method_return_error(context, error);
516                 g_error_free(error);
517                 return FALSE;
518         }
519
520         dbus_g_method_return(context);
521
522         DBG("bt_hfp_agent_incoming_call - \n");
523         return TRUE;
524 }
525
526 static gboolean bt_hfp_agent_outgoing_call(BtHfpAgent *agent, const gchar *path,
527                                 const gchar *number, gint call_id,
528                                 DBusGMethodInvocation *context)
529 {
530         GError *error;
531         char *sender;
532         int ret;
533
534         DBG("bt_hfp_agent_outgoing_call + \n");
535
536         if (path == NULL || number == NULL) {
537                 DBG("Invalid Arguments\n");
538                 error = __bt_hfp_agent_set_error(
539                                         BT_HFP_AGENT_ERROR_INVALID_PARAM);
540                 dbus_g_method_return_error(context, error);
541                 g_error_free(error);
542                 return FALSE;
543         }
544
545         DBG("Application path = %s\n", path);
546         DBG("Phone number = %s\n", number);
547         DBG("Call id = %d\n", call_id);
548
549         sender = dbus_g_method_get_sender(context);
550
551         DBG("Sender = %s\n", sender);
552
553         ret = __bt_hfp_agent_dbus_method_send(BLUEZ_SERVICE_NAME,
554                                 TELEPHONY_CSD_OBJECT_PATH,
555                                 TELEPHONY_CSD_INTERFACE,
556                                 "Outgoing", TRUE,
557                                 DBUS_TYPE_STRING, &path,
558                                 DBUS_TYPE_STRING, &number,
559                                 DBUS_TYPE_UINT32, &call_id,
560                                 DBUS_TYPE_STRING, &sender,
561                                 DBUS_TYPE_INVALID);
562         g_free(sender);
563
564         if (ret != BT_HFP_AGENT_ERROR_NONE) {
565                 error = __bt_hfp_agent_set_error(ret);
566                 dbus_g_method_return_error(context, error);
567                 g_error_free(error);
568                 return FALSE;
569         }
570
571         dbus_g_method_return(context);
572
573         DBG("bt_hfp_agent_outgoing_call - \n");
574         return TRUE;
575 }
576
577 static gboolean bt_hfp_agent_change_call_status(BtHfpAgent *agent,
578                                 const gchar *path, gint status, gint call_id,
579                                 DBusGMethodInvocation *context)
580 {
581         GError *error;
582         char *sender;
583         int ret;
584
585         DBG("bt_hfp_agent_change_call_status + \n");
586
587         if (path == NULL) {
588                 DBG("Invalid Argument path\n");
589                 error = __bt_hfp_agent_set_error(
590                                         BT_HFP_AGENT_ERROR_INVALID_PARAM);
591                 dbus_g_method_return_error(context, error);
592                 g_error_free(error);
593                 return FALSE;
594         }
595
596         DBG("Application path = %s\n", path);
597         DBG("Status = %d\n", status);
598         DBG("Call id = %d\n", call_id);
599
600         sender = dbus_g_method_get_sender(context);
601
602         DBG("Sender = %s\n", sender);
603
604         ret = __bt_hfp_agent_dbus_method_send(BLUEZ_SERVICE_NAME,
605                                 TELEPHONY_CSD_OBJECT_PATH,
606                                 TELEPHONY_CSD_INTERFACE,
607                                 "SetCallStatus", TRUE,
608                                 DBUS_TYPE_STRING, &path,
609                                 DBUS_TYPE_UINT32, &status,
610                                 DBUS_TYPE_UINT32, &call_id,
611                                 DBUS_TYPE_STRING, &sender,
612                                 DBUS_TYPE_INVALID);
613         g_free(sender);
614
615         if (ret != BT_HFP_AGENT_ERROR_NONE) {
616                 error = __bt_hfp_agent_set_error(ret);
617                 dbus_g_method_return_error(context, error);
618                 g_error_free(error);
619                 return FALSE;
620         }
621
622         dbus_g_method_return(context);
623
624         DBG("bt_hfp_agent_change_call_status - \n");
625         return TRUE;
626 }
627
628 static gboolean bt_hfp_agent_answer_call(BtHfpAgent *agent, unsigned int call_id,
629                                 const gchar *path, const gchar *sender,
630                                 DBusGMethodInvocation *context)
631 {
632         int ret;
633         GError *error;
634         DBG("+\n");
635
636         if (path == NULL || sender == NULL) {
637                 DBG("Invalid Arguments\n");
638                 error = __bt_hfp_agent_set_error(
639                                         BT_HFP_AGENT_ERROR_INVALID_PARAM);
640                 dbus_g_method_return_error(context, error);
641                 g_error_free(error);
642                 return FALSE;
643         }
644
645         DBG("Application path = %s \n", path);
646         DBG("Call Id = %d", call_id);
647         DBG("Sender = %s\n", sender);
648
649         ret = __bt_hfp_agent_dbus_method_send(sender,
650                                 path, TELEPHONY_APP_INTERFACE,
651                                 "Answer", FALSE,
652                                 DBUS_TYPE_UINT32, &call_id,
653                                 DBUS_TYPE_INVALID);
654
655         if (ret != BT_HFP_AGENT_ERROR_NONE) {
656                 error = __bt_hfp_agent_set_error(ret);
657                 dbus_g_method_return_error(context, error);
658                 g_error_free(error);
659                 return FALSE;
660         }
661
662         dbus_g_method_return(context);
663
664         DBG("-\n");
665         return TRUE;
666 }
667
668 static gboolean bt_hfp_agent_release_call(BtHfpAgent *agent, unsigned int call_id,
669                                 const gchar *path, const gchar *sender,
670                                 DBusGMethodInvocation *context)
671 {
672         int ret;
673         GError *error;
674         DBG("+\n");
675
676         if (path == NULL || sender == NULL) {
677                 DBG("Invalid Arguments\n");
678                 error = __bt_hfp_agent_set_error(
679                                         BT_HFP_AGENT_ERROR_INVALID_PARAM);
680                 dbus_g_method_return_error(context, error);
681                 g_error_free(error);
682                 return FALSE;
683         }
684
685         DBG("Application path = %s \n", path);
686         DBG("Call Id = %d", call_id);
687         DBG("Sender = %s\n", sender);
688
689         ret = __bt_hfp_agent_dbus_method_send(sender,
690                                 path, TELEPHONY_APP_INTERFACE,
691                                 "Release", FALSE,
692                                 DBUS_TYPE_UINT32, &call_id,
693                                 DBUS_TYPE_INVALID);
694
695         if (ret != BT_HFP_AGENT_ERROR_NONE) {
696                 error = __bt_hfp_agent_set_error(ret);
697                 dbus_g_method_return_error(context, error);
698                 g_error_free(error);
699                 return FALSE;
700         }
701
702         dbus_g_method_return(context);
703         DBG("-\n");
704         return TRUE;
705 }
706
707 static gboolean bt_hfp_agent_reject_call(BtHfpAgent *agent, unsigned int call_id,
708                                 const gchar *path, const gchar *sender,
709                                 DBusGMethodInvocation *context)
710 {
711         int ret;
712         GError *error;
713         DBG("+\n");
714
715         if (path == NULL || sender == NULL) {
716                 DBG("Invalid Arguments\n");
717                 error = __bt_hfp_agent_set_error(
718                                         BT_HFP_AGENT_ERROR_INVALID_PARAM);
719                 dbus_g_method_return_error(context, error);
720                 g_error_free(error);
721                 return FALSE;
722         }
723
724         DBG("Application path = %s \n", path);
725         DBG("Call Id = %d", call_id);
726         DBG("Sender = %s\n", sender);
727
728         ret = __bt_hfp_agent_dbus_method_send(sender,
729                                 path, TELEPHONY_APP_INTERFACE,
730                                 "Reject", FALSE,
731                                 DBUS_TYPE_UINT32, &call_id,
732                                 DBUS_TYPE_INVALID);
733
734         if (ret != BT_HFP_AGENT_ERROR_NONE) {
735                 error = __bt_hfp_agent_set_error(ret);
736                 dbus_g_method_return_error(context, error);
737                 g_error_free(error);
738                 return FALSE;
739         }
740
741         dbus_g_method_return(context);
742         DBG("-\n");
743         return TRUE;
744 }
745
746 static gboolean bt_hfp_agent_threeway_call(BtHfpAgent *agent, gint value,
747                                 const gchar *path, const gchar *sender,
748                                 DBusGMethodInvocation *context)
749 {
750         int ret;
751         GError *error;
752         DBG("+\n");
753
754         if (path == NULL || sender == NULL) {
755                 DBG("Invalid Arguments\n");
756                 error = __bt_hfp_agent_set_error(
757                                         BT_HFP_AGENT_ERROR_INVALID_PARAM);
758                 dbus_g_method_return_error(context, error);
759                 g_error_free(error);
760                 return FALSE;
761         }
762
763         DBG("Application path = %s \n", path);
764         DBG("Value = %d", value);
765         DBG("Sender = %s\n", sender);
766
767         ret = __bt_hfp_agent_dbus_method_send(sender,
768                                 path, TELEPHONY_APP_INTERFACE,
769                                 "Threeway", TRUE,
770                                 DBUS_TYPE_UINT32, &value,
771                                 DBUS_TYPE_INVALID);
772
773         if (ret != BT_HFP_AGENT_ERROR_NONE) {
774                 error = __bt_hfp_agent_set_error(ret);
775                 dbus_g_method_return_error(context, error);
776                 g_error_free(error);
777                 return FALSE;
778         }
779
780         dbus_g_method_return(context);
781         DBG("-\n");
782         return TRUE;
783 }
784
785 void __bt_append_entry(DBusMessageIter *iter,
786                         const char *key, int type, void *val)
787 {
788         DBusMessageIter entry;
789         DBusMessageIter value;
790         const char *str;
791         char signal[BT_SIGNAL_ARRAY_MAX] = { type, '\0' };
792
793         if (type == DBUS_TYPE_STRING) {
794                 str = *((const char **) val);
795                 if (str == NULL) {
796                         return;
797                 }
798         }
799
800         dbus_message_iter_open_container(iter, DBUS_TYPE_DICT_ENTRY,
801                                                         NULL, &entry);
802         dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
803
804         dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
805                                                 signal, &value);
806
807         dbus_message_iter_append_basic(&value, type, val);
808
809         dbus_message_iter_close_container(&entry, &value);
810
811         dbus_message_iter_close_container(iter, &entry);
812 }
813
814 static gboolean bt_hfp_agent_get_properties(BtHfpAgent *agent,
815                                 DBusGMethodInvocation *context)
816 {
817         DBusMessage *reply;
818         DBusMessageIter iter;
819         DBusMessageIter dict;
820         GError *error;
821
822         DBG("bt_hfp_agent_get_properties + \n");
823
824         reply = dbus_g_method_get_reply(context);
825         if (!reply) {
826                 error = __bt_hfp_agent_set_error(BT_HFP_AGENT_ERROR_INTERNAL);
827                 dbus_g_method_return_error(context, error);
828                 g_error_free(error);
829                 return FALSE;
830         }
831
832         dbus_message_iter_init_append(reply, &iter);
833
834         dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
835                         DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
836                         DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
837                         DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
838
839         __bt_append_entry(&dict, "nrec", DBUS_TYPE_BOOLEAN, &nrec_status);
840         dbus_message_iter_close_container(&iter, &dict);
841         dbus_g_method_send_reply(context, reply);
842         DBG("bt_hfp_agent_get_properties - \n");
843         return TRUE;
844 }
845
846 static gboolean __bt_is_phone_locked(int *phone_lock_state)
847 {
848         int ret;
849         DBG("+\n");
850
851         if (NULL == phone_lock_state)
852                 return FALSE;
853
854         ret = vconf_get_int(VCONFKEY_IDLE_LOCK_STATE, phone_lock_state);
855         if (ret != 0) {
856                 DBG("Failed to read  [%s]\n", VCONFKEY_IDLE_LOCK_STATE);
857                 return FALSE;
858         }
859
860         DBG("[%s] = [%d]\n", VCONFKEY_IDLE_LOCK_STATE, *phone_lock_state);
861         DBG("-\n");
862
863         return TRUE;
864 }
865
866 static gboolean __bt_get_outgoing_callapp_type(int *callapp_type)
867 {
868         int ret;
869         DBG(" +\n");
870
871         if (NULL == callapp_type)
872                 return FALSE;
873
874         ret = vconf_get_int(VCONFKEY_CISSAPPL_OUTGOING_CALL_TYPE_INT, callapp_type);
875         if (ret != 0) {
876                 DBG("Failed to read  [%s]\n", VCONFKEY_CISSAPPL_OUTGOING_CALL_TYPE_INT);
877                 return FALSE;
878         }
879
880         DBG(" [%s] = [%d]\n", VCONFKEY_CISSAPPL_OUTGOING_CALL_TYPE_INT, *callapp_type);
881         DBG("-\n");
882
883         return TRUE;
884 }
885
886 static gboolean __bt_get_outgoing_call_condition(int *condition)
887 {
888         int ret;
889         DBG("+\n");
890
891         if (NULL == condition)
892                 return FALSE;
893
894         ret = vconf_get_int(VCONFKEY_CISSAPPL_OUTGOING_CALL_CONDITIONS_INT, condition);
895         if (ret != 0) {
896                 DBG("Failed to read  [%s]\n", VCONFKEY_CISSAPPL_OUTGOING_CALL_CONDITIONS_INT);
897                 return FALSE;
898         }
899
900         DBG(" [%s] = [%d]\n", VCONFKEY_CISSAPPL_OUTGOING_CALL_CONDITIONS_INT, *condition);
901         DBG("-\n");
902
903         return TRUE;
904 }
905
906 static gboolean __bt_hfp_agent_make_call(const char *number)
907 {
908         bundle *b;
909         char telnum[BT_MAX_TEL_NUM_STRING];
910
911         b = bundle_create();
912         if (NULL == b)
913                 return FALSE;
914
915         appsvc_set_operation(b, APPSVC_OPERATION_CALL);
916         snprintf(telnum, sizeof(telnum), "tel:%s", number);
917         appsvc_set_uri(b, telnum);
918         appsvc_add_data(b, "ctindex", "-1");
919         appsvc_run_service(b, 0, NULL, NULL);
920         bundle_free(b);
921
922         return TRUE;
923 }
924
925 static gboolean __bt_hfp_agent_make_video_call(const char *mo_number)
926 {
927         bundle *kb;
928
929         kb = bundle_create();
930         if (NULL == kb)
931                 return FALSE;
932
933         bundle_add(kb, "KEY_CALL_TYPE", "MO");
934         bundle_add(kb, "number", mo_number);
935         aul_launch_app("com.samsung.vtmain", kb);
936         bundle_free(kb);
937
938         return TRUE;
939 }
940
941 static gboolean bt_hfp_agent_dial_last_num(BtHfpAgent *agent,
942                                 DBusGMethodInvocation *context)
943 {
944         GError *error;
945         int error_code = BT_HFP_AGENT_ERROR_NONE;
946         char *last_number = NULL;
947         int log_type;
948         int callapp_type;
949         int phone_lock_state;
950         int condition;
951         contacts_list_h list = NULL;
952         contacts_query_h query = NULL;
953         contacts_filter_h filter = NULL;
954         contacts_record_h record = NULL;
955         unsigned int projections[] = {
956                 _contacts_phone_log.address,
957                 _contacts_phone_log.log_type,
958         };
959
960         DBG("+ \n");
961
962         if (contacts_connect2() != CONTACTS_ERROR_NONE) {
963                 ERR(" contacts_connect2 failed \n");
964                 error = __bt_hfp_agent_set_error(BT_HFP_AGENT_ERROR_INTERNAL);
965                 dbus_g_method_return_error(context, error);
966                 g_error_free(error);
967                 return FALSE;
968         }
969
970         contacts_filter_create(_contacts_phone_log._uri, &filter);
971
972         if (filter == NULL)
973                 goto done;
974
975         if (contacts_filter_add_int(filter, _contacts_phone_log.log_type,
976                                 CONTACTS_MATCH_EQUAL,
977                                 CONTACTS_PLOG_TYPE_VOICE_OUTGOING) !=
978                                 CONTACTS_ERROR_NONE) {
979                 ERR(" contacts_filter_add_int failed \n");
980                 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
981                 goto done;
982         }
983
984         if (contacts_filter_add_operator(filter, CONTACTS_FILTER_OPERATOR_OR) !=
985                                 CONTACTS_ERROR_NONE) {
986                 ERR(" contacts_filter_add_operator failed \n");
987                 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
988                 goto done;
989         }
990
991         if (contacts_filter_add_int(filter, _contacts_phone_log.log_type,
992                                 CONTACTS_MATCH_EQUAL,
993                                 CONTACTS_PLOG_TYPE_VIDEO_OUTGOING) !=
994                                 CONTACTS_ERROR_NONE) {
995                 ERR(" contacts_filter_add_int failed \n");
996                 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
997                 goto done;
998         }
999
1000         contacts_query_create(_contacts_phone_log._uri, &query);
1001
1002         if (query == NULL)
1003                 goto done;
1004
1005         contacts_query_set_filter(query, filter);
1006
1007         if (contacts_query_set_projection(query, projections,
1008                                 sizeof(projections)/sizeof(unsigned int)) !=
1009                                 CONTACTS_ERROR_NONE) {
1010                 ERR(" contacts_query_set_projection failed \n");
1011                 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
1012                 goto done;
1013         }
1014
1015         if (contacts_query_set_sort(query, _contacts_phone_log.log_time, false) !=
1016                                 CONTACTS_ERROR_NONE) {
1017                 ERR(" contacts_query_set_sort failed \n");
1018                 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
1019                 goto done;
1020         }
1021
1022         if (contacts_db_get_records_with_query(query, 0, 1, &list)  !=
1023                                 CONTACTS_ERROR_NONE) {
1024                 ERR(" contacts_db_get_records_with_query failed \n");
1025                 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
1026                 goto done;
1027         }
1028
1029         if (contacts_list_first(list)  != CONTACTS_ERROR_NONE) {
1030                 ERR(" contacts_list_first failed \n");
1031                 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
1032                 goto done;
1033         }
1034
1035         if (contacts_list_get_current_record_p(list, &record)  !=
1036                                 CONTACTS_ERROR_NONE) {
1037                 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
1038                 goto done;
1039         }
1040
1041         if (record == NULL)
1042                 goto done;
1043
1044         if (contacts_record_get_str(record, _contacts_phone_log.address,
1045                                 &last_number)!= CONTACTS_ERROR_NONE) {
1046                 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
1047                 goto done;
1048         }
1049
1050         if (last_number == NULL) {
1051                 ERR("No last number \n");
1052                 error_code = BT_HFP_AGENT_ERROR_NO_CALL_LOGS;
1053                 goto done;
1054         }
1055
1056         if (!__bt_is_phone_locked(&phone_lock_state)) {
1057                 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
1058                 goto done;
1059         }
1060
1061         if (!__bt_get_outgoing_callapp_type(&callapp_type)) {
1062                 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
1063                 goto done;
1064         }
1065
1066         if (!__bt_get_outgoing_call_condition(&condition)) {
1067                 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
1068                 goto done;
1069         }
1070
1071         if (condition == BT_MO_ONLY_UNLOCKED &&
1072                 phone_lock_state == VCONFKEY_IDLE_LOCK) {
1073                 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
1074                 goto done;
1075         }
1076
1077         switch (callapp_type) {
1078                 case BT_VOICE_CALL:
1079                         if (!__bt_hfp_agent_make_call(last_number)) {
1080                                 ERR("Problem launching application \n");
1081                                 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
1082                         }
1083                         break;
1084                 case BT_VIDEO_CALL:
1085                         if(!__bt_hfp_agent_make_video_call(last_number)) {
1086                                 ERR("Problem launching application \n");
1087                                 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
1088                         }
1089                         break;
1090                 case BT_FOLLOW_CALL_LOG:
1091                         if(contacts_record_get_int(record,
1092                                 _contacts_phone_log.log_type,
1093                                 &log_type) != CONTACTS_ERROR_NONE) {
1094                                 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
1095                                 break;
1096                         }
1097                         if (log_type == CONTACTS_PLOG_TYPE_VOICE_OUTGOING) {
1098                                 if (!__bt_hfp_agent_make_call(last_number)) {
1099                                         ERR("Problem launching application \n");
1100                                         error_code = BT_HFP_AGENT_ERROR_INTERNAL;
1101                                 }
1102                         }
1103                         else if(log_type == CONTACTS_PLOG_TYPE_VIDEO_OUTGOING) {
1104                                 if(!__bt_hfp_agent_make_video_call(last_number)) {
1105                                         ERR("Problem launching application \n");
1106                                         error_code = BT_HFP_AGENT_ERROR_INTERNAL;
1107                                 }
1108                         } else {
1109                                 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
1110                         }
1111                         break;
1112                 default:
1113                         error_code = BT_HFP_AGENT_ERROR_INTERNAL;
1114                         break;
1115         }
1116
1117 done:
1118         if (list != NULL)
1119                 contacts_list_destroy(list, TRUE);
1120
1121         if (filter != NULL)
1122                 contacts_filter_destroy(filter);
1123
1124         if (query != NULL)
1125                 contacts_query_destroy(query);
1126
1127         contacts_disconnect2();
1128
1129         if (last_number != NULL)
1130                 g_free(last_number);
1131
1132         DBG("-\n");
1133
1134         if (error_code == BT_HFP_AGENT_ERROR_NONE) {
1135                 dbus_g_method_return(context);
1136                 return TRUE;
1137         } else {
1138                 error = __bt_hfp_agent_set_error(error_code);
1139                 dbus_g_method_return_error(context, error);
1140                 g_error_free(error);
1141                 return FALSE;
1142         }
1143 }
1144
1145 static gboolean bt_hfp_agent_dial_num(BtHfpAgent *agent,
1146                                 const gchar *number, guint flags,
1147                                 DBusGMethodInvocation *context)
1148 {
1149         GError *error;
1150         int error_code;
1151         int callapp_type;
1152         int phone_lock_state;
1153         int condition;
1154
1155         DBG("+\n");
1156
1157         if (number == NULL) {
1158                 ERR("Invalid Argument\n");
1159                 error_code = BT_HFP_AGENT_ERROR_INVALID_PARAM;
1160                 goto fail;
1161         }
1162
1163         DBG("Number = %s \n", number);
1164         DBG("flags = %d", flags);
1165
1166         /*TODO: Make use of flags*/
1167
1168         if (!__bt_is_phone_locked(&phone_lock_state)) {
1169                 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
1170                 goto fail;
1171         }
1172
1173         if (!__bt_get_outgoing_callapp_type(&callapp_type)) {
1174                 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
1175                 goto fail;
1176         }
1177
1178         if (!__bt_get_outgoing_call_condition(&condition)) {
1179                 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
1180                 goto fail;
1181         }
1182
1183         if (condition == BT_MO_ONLY_UNLOCKED && phone_lock_state == VCONFKEY_IDLE_LOCK) {
1184                 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
1185                 goto fail;
1186         }
1187
1188         if (callapp_type == BT_VIDEO_CALL) {
1189                 if(!__bt_hfp_agent_make_video_call(number)) {
1190                         ERR("Problem launching application \n");
1191                         error_code = BT_HFP_AGENT_ERROR_INTERNAL;
1192                         goto fail;
1193                 }
1194         } else {
1195                 if (!__bt_hfp_agent_make_call(number)) {
1196                         ERR("Problem launching application \n");
1197                         error_code = BT_HFP_AGENT_ERROR_INTERNAL;
1198                         goto fail;
1199                 }
1200         }
1201
1202         dbus_g_method_return(context);
1203
1204         DBG("-\n");
1205         return TRUE;
1206 fail:
1207         error = __bt_hfp_agent_set_error(error_code);
1208         dbus_g_method_return_error(context, error);
1209         g_error_free(error);
1210         DBG("-\n");
1211         return FALSE;
1212 }
1213
1214 static gboolean bt_hfp_agent_dial_memory(BtHfpAgent *agent, gint location,
1215                                 DBusGMethodInvocation *context)
1216 {
1217         GError *error;
1218         int error_code = BT_HFP_AGENT_ERROR_NONE;
1219         char *number = NULL;
1220         contacts_filter_h filter = NULL;
1221         contacts_query_h query = NULL;
1222         contacts_list_h list = NULL;
1223         contacts_record_h record = NULL;
1224         unsigned int projections[] = {
1225                 _contacts_speeddial.number,
1226         };
1227
1228         DBG("+\n");
1229
1230         DBG("location = %d \n", location);
1231
1232         /*Get number from contacts location*/
1233         if (contacts_connect2() != CONTACTS_ERROR_NONE) {
1234                 ERR(" contacts_connect2 failed \n");
1235                 error = __bt_hfp_agent_set_error(BT_HFP_AGENT_ERROR_INTERNAL);
1236                 dbus_g_method_return_error(context, error);
1237                 g_error_free(error);
1238                 return FALSE;
1239         }
1240
1241         contacts_filter_create(_contacts_speeddial._uri, &filter);
1242
1243         if (filter == NULL)
1244                 goto done;
1245
1246         if (contacts_filter_add_int(filter, _contacts_speeddial.speeddial_number,
1247                                 CONTACTS_MATCH_EQUAL, location) !=
1248                                 CONTACTS_ERROR_NONE) {
1249                 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
1250                 goto done;
1251         }
1252
1253         contacts_query_create(_contacts_speeddial._uri, &query);
1254
1255         if (query == NULL)
1256                 goto done;
1257
1258         contacts_query_set_filter(query, filter);
1259
1260         if (contacts_query_set_projection(query, projections,
1261                                 sizeof(projections)/sizeof(unsigned int)) !=
1262                                 CONTACTS_ERROR_NONE) {
1263                 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
1264                 goto done;
1265         }
1266
1267         if (contacts_db_get_records_with_query(query, 0, 1, &list) !=
1268                                 CONTACTS_ERROR_NONE) {
1269                 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
1270                 goto done;
1271         }
1272
1273         if (contacts_list_first(list) != CONTACTS_ERROR_NONE) {
1274                 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
1275                 goto done;
1276         }
1277
1278         if (contacts_list_get_current_record_p(list, &record) !=
1279                                 CONTACTS_ERROR_NONE) {
1280                 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
1281                 goto done;
1282         }
1283
1284         if (record == NULL)
1285                 goto done;
1286
1287         if (contacts_record_get_str(record, _contacts_speeddial.number,
1288                                                         &number)!= CONTACTS_ERROR_NONE) {
1289                 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
1290                 goto done;
1291         }
1292
1293         if (number == NULL) {
1294                 ERR("No number at the location \n");
1295                 error_code = BT_HFP_AGENT_ERROR_INVALID_MEMORY_INDEX;
1296                 goto done;
1297         }
1298
1299         DBG("number %s\n", number);
1300
1301         /*Make Voice call*/
1302         if (!__bt_hfp_agent_make_call(number)) {
1303                 ERR("Problem launching application \n");
1304                 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
1305         }
1306
1307         g_free(number);
1308 done:
1309         if (list != NULL)
1310                 contacts_list_destroy(list, TRUE);
1311
1312         if (filter != NULL)
1313                 contacts_filter_destroy(filter);
1314
1315         if (query != NULL)
1316                 contacts_query_destroy(query);
1317
1318         contacts_disconnect2();
1319
1320         DBG("-\n");
1321
1322         if (error_code == BT_HFP_AGENT_ERROR_NONE) {
1323                 dbus_g_method_return(context);
1324                 return TRUE;
1325         } else {
1326                 error = __bt_hfp_agent_set_error(error_code);
1327                 dbus_g_method_return_error(context, error);
1328                 g_error_free(error);
1329                 return FALSE;
1330         }
1331 }
1332
1333 static gboolean bt_hfp_agent_send_dtmf(BtHfpAgent *agent, const gchar *dtmf,
1334                                 const gchar *path, const gchar *sender,
1335                                 DBusGMethodInvocation *context)
1336 {
1337         GError *error;
1338         int ret;
1339
1340         DBG("+\n");
1341
1342         if (dtmf == NULL || path == NULL || sender == NULL) {
1343                 ERR("Invalid Argument\n");
1344                 error = __bt_hfp_agent_set_error(
1345                                         BT_HFP_AGENT_ERROR_INVALID_PARAM);
1346                 dbus_g_method_return_error(context, error);
1347                 g_error_free(error);
1348                 return FALSE;
1349         }
1350
1351         DBG("Dtmf = %s \n", dtmf);
1352         DBG("Application path = %s \n", path);
1353         DBG("Sender = %s\n", sender);
1354
1355         ret = __bt_hfp_agent_dbus_method_send(sender,
1356                                 path, TELEPHONY_APP_INTERFACE,
1357                                 "SendDtmf", FALSE,
1358                                 DBUS_TYPE_STRING, &dtmf,
1359                                 DBUS_TYPE_INVALID);
1360
1361         if (ret != BT_HFP_AGENT_ERROR_NONE) {
1362                 error = __bt_hfp_agent_set_error(ret);
1363                 dbus_g_method_return_error(context, error);
1364                 g_error_free(error);
1365                 return FALSE;
1366         }
1367
1368         /*App Selector code here needed*/
1369         dbus_g_method_return(context);
1370
1371         DBG("-\n");
1372         return TRUE;
1373 }
1374
1375 static void __bt_hfp_agent_launch_voice_dial(gboolean activate)
1376 {
1377         service_h service = NULL;
1378
1379         service_create(&service);
1380
1381         if (service == NULL) {
1382                 DBG("Service create failed");
1383                 return;
1384         }
1385
1386         service_set_package(service, "com.samsung.svoice");
1387         service_set_operation(service, SERVICE_OPERATION_DEFAULT);
1388         service_add_extra_data(service, "domain", "bt_headset");
1389
1390         if (!activate)
1391                 service_add_extra_data(service, "action_type", "deactivate");
1392
1393         if (service_send_launch_request(service, NULL, NULL) !=
1394                                                 SERVICE_ERROR_NONE)
1395                 DBG("launch failed");
1396
1397         service_destroy(service);
1398         return;
1399 }
1400
1401 static gboolean bt_hfp_agent_voice_dial(BtHfpAgent *agent, gboolean activate,
1402                                 DBusGMethodInvocation *context)
1403 {
1404         DBG("Activate = %d \n", activate);
1405
1406         __bt_hfp_agent_launch_voice_dial(activate);
1407         dbus_g_method_return(context);
1408
1409         DBG("-\n");
1410         return TRUE;
1411 }
1412
1413 static gboolean bt_hfp_agent_get_battery_status(BtHfpAgent *object,
1414                                 DBusGMethodInvocation *context)
1415 {
1416         gint battery_chrg_status;
1417         gint battery_capacity;
1418         GError *error;
1419
1420         DBG("+\n");
1421
1422         if (vconf_get_int(VCONFKEY_SYSMAN_BATTERY_CHARGE_NOW,
1423                                                 &battery_chrg_status)) {
1424                 DBG("VCONFKEY_SYSMAN_BATTERY_CHARGE_NOW failed\n");
1425                 goto fail;
1426         }
1427
1428         DBG("Status : %d\n", battery_chrg_status);
1429
1430         if (vconf_get_int(VCONFKEY_SYSMAN_BATTERY_CAPACITY,
1431                                                 &battery_capacity)) {
1432                 DBG("VCONFKEY_SYSMAN_BATTERY_CAPACITY failed\n");
1433                 goto fail;
1434         }
1435
1436         DBG("Capacity : %d\n", battery_capacity);
1437
1438         dbus_g_method_return(context, battery_chrg_status, battery_capacity);
1439         DBG("-\n");
1440         return TRUE;
1441
1442 fail:
1443         error = __bt_hfp_agent_set_error(BT_HFP_AGENT_ERROR_BATTERY_STATUS);
1444         dbus_g_method_return_error(context, error);
1445         g_error_free(error);
1446         DBG("-\n");
1447         return FALSE;
1448 }
1449
1450 static gboolean bt_hfp_agent_get_signal_quality(BtHfpAgent *object,
1451                                         DBusGMethodInvocation *context)
1452 {
1453         gint rssi;
1454         GError *error;
1455
1456         DBG("+\n");
1457
1458         if (vconf_get_int(VCONFKEY_TELEPHONY_RSSI, &rssi)) {
1459                 DBG("VCONFKEY_TELEPHONY_RSSI failed\n");
1460                 goto fail;
1461         }
1462
1463         DBG("RSSI : %d \n", rssi);
1464
1465         dbus_g_method_return(context, rssi, BT_SIGNAL_QUALITY_BER);
1466         DBG("-\n");
1467         return TRUE;
1468 fail:
1469         error = __bt_hfp_agent_set_error(BT_HFP_AGENT_ERROR_SIGNAL_STATUS);
1470         dbus_g_method_return_error(context, error);
1471         g_error_free(error);
1472         DBG("-\n");
1473         return FALSE;
1474 }
1475
1476 static gboolean bt_hfp_agent_get_operator_name(BtHfpAgent *object,
1477                                 DBusGMethodInvocation *context)
1478 {
1479         char *operator_name;
1480         GError *error;
1481
1482         DBG(" +\n");
1483
1484         operator_name = vconf_get_str(VCONFKEY_TELEPHONY_NWNAME);
1485         if (NULL == operator_name) {
1486                 DBG("vconf_get_str failed \n");
1487                 error = __bt_hfp_agent_set_error(BT_HFP_AGENT_ERROR_INTERNAL);
1488                 dbus_g_method_return_error(context, error);
1489                 g_error_free(error);
1490                 return FALSE;
1491         }
1492
1493         DBG("operator_name  = [%s] \n", operator_name);
1494
1495         dbus_g_method_return(context, operator_name);
1496         free(operator_name);
1497
1498         DBG(" -\n");
1499         return TRUE;
1500 }
1501
1502 static gboolean bt_hfp_agent_nrec_status(BtHfpAgent *agent, gboolean status,
1503                                 DBusGMethodInvocation *context)
1504 {
1505         DBusMessage *signal;
1506
1507         DBG("+\n");
1508
1509         DBG("NREC status = %d \n", status);
1510         nrec_status = status;
1511         dbus_g_method_return(context);
1512
1513         /*Emit NREC Status change signal with value*/
1514         signal = dbus_message_new_signal(BT_HFP_AGENT_OBJECT,
1515                                         BT_HFP_AGENT_INTERFACE,
1516                                         "NrecStatusChanged");
1517         if (!signal)
1518                 return FALSE;
1519
1520         if (!dbus_message_append_args(signal,
1521                                 DBUS_TYPE_BOOLEAN, &status,
1522                                 DBUS_TYPE_INVALID)) {
1523                 DBG("Signal appending failed\n");
1524                 dbus_message_unref(signal);
1525                 return FALSE;
1526         }
1527
1528         dbus_connection_send(gconn, signal, NULL);
1529         dbus_message_unref(signal);
1530         DBG("-\n");
1531         return TRUE;
1532 }
1533
1534 static void __bt_hfp_agent_append_variant(DBusMessageIter *iter,
1535                         int type, void *val)
1536 {
1537         DBusMessageIter value_iter;
1538         const char *variant;
1539
1540         switch (type) {
1541         case DBUS_TYPE_BOOLEAN:
1542                 variant = DBUS_TYPE_BOOLEAN_AS_STRING;
1543                 break;
1544         case DBUS_TYPE_STRING:
1545                 variant = DBUS_TYPE_STRING_AS_STRING;
1546                 break;
1547         case DBUS_TYPE_BYTE:
1548                 variant = DBUS_TYPE_BYTE_AS_STRING;
1549                 break;
1550         case DBUS_TYPE_UINT16:
1551                 variant = DBUS_TYPE_UINT16_AS_STRING;
1552                 break;
1553         case DBUS_TYPE_UINT32:
1554                 variant = DBUS_TYPE_UINT32_AS_STRING;
1555                 break;
1556         case DBUS_TYPE_INT16:
1557                 variant = DBUS_TYPE_INT16_AS_STRING;
1558                 break;
1559         case DBUS_TYPE_INT32:
1560                 variant = DBUS_TYPE_INT32_AS_STRING;
1561                 break;
1562         case DBUS_TYPE_OBJECT_PATH:
1563                 variant = DBUS_TYPE_OBJECT_PATH_AS_STRING;
1564                 break;
1565         default:
1566                 variant = DBUS_TYPE_VARIANT_AS_STRING;
1567                 break;
1568         }
1569
1570         dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, variant,
1571                                                         &value_iter);
1572         dbus_message_iter_append_basic(&value_iter, type, val);
1573         dbus_message_iter_close_container(iter, &value_iter);
1574 }
1575
1576 static gboolean __bt_hfp_agent_dbus_method_variant_send(const char *path,
1577                 const char *interface, const char *method, const char *name,
1578                 int type, void *value)
1579 {
1580         DBusMessage *msg;
1581         DBusMessage *reply;
1582         DBusError err;
1583         DBusMessageIter iter;
1584
1585         DBG(" +\n");
1586
1587         msg = dbus_message_new_method_call(BLUEZ_SERVICE_NAME,
1588                         path, interface, method);
1589
1590         if (!msg) {
1591                 DBG("Unable to allocate new D-Bus %s message", method);
1592                 return FALSE;
1593         }
1594
1595         dbus_message_iter_init_append(msg, &iter);
1596
1597         dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &name);
1598
1599         __bt_hfp_agent_append_variant(&iter, type, value);
1600
1601         dbus_error_init(&err);
1602
1603         reply = dbus_connection_send_with_reply_and_block(gconn,
1604                                 msg, -1, &err);
1605
1606         dbus_message_unref(msg);
1607
1608         if (!reply) {
1609                 DBG("Error returned in method call\n");
1610                 if (dbus_error_is_set(&err)) {
1611                         if (err.message != NULL) {
1612                                 DBG("Error message = %s\n", err.message);
1613                         }
1614                         dbus_error_free(&err);
1615                 }
1616                 return FALSE;
1617         }
1618
1619         dbus_message_unref(reply);
1620
1621         DBG(" -\n");
1622         return TRUE;
1623 }
1624
1625 static gboolean __bt_hfp_agent_send_registration_status_changed(
1626                 bt_hfp_agent_network_registration_status_t status)
1627 {
1628         const char *property = g_strdup("RegistrationChanged");
1629
1630         DBG(" +\n");
1631
1632         if (!__bt_hfp_agent_dbus_method_variant_send(TELEPHONY_CSD_OBJECT_PATH,
1633                         TELEPHONY_CSD_INTERFACE,
1634                         BT_HFP_AGENT_SET_PROPERTY,
1635                         property, DBUS_TYPE_BYTE, &status)) {
1636                 DBG("__bt_hfp_agent_dbus_method_variant_send - ERROR\n");
1637                 g_free((void *)property);
1638                 return FALSE;
1639         }
1640         DBG(" -\n");
1641
1642         g_free((void *)property);
1643         return TRUE;
1644 }
1645
1646 static gboolean __bt_hfp_agent_send_subscriber_number_changed(
1647                                                         const char *number)
1648 {
1649         const char *property = g_strdup("SubscriberNumberChanged");
1650
1651         DBG(" +\n");
1652
1653         if (!__bt_hfp_agent_dbus_method_variant_send(TELEPHONY_CSD_OBJECT_PATH,
1654                         TELEPHONY_CSD_INTERFACE,
1655                         BT_HFP_AGENT_SET_PROPERTY,
1656                         property,
1657                         DBUS_TYPE_STRING, &number)) {
1658                 DBG("__bt_hfp_agent_dbus_method_variant_send - ERROR\n");
1659                 g_free((void *)property);
1660                 return FALSE;
1661         }
1662
1663         DBG(" -\n");
1664         g_free((void *)property);
1665         return TRUE;
1666 }
1667
1668 static gboolean __bt_hfp_agent_send_signal_bar_changed(int signal_bar)
1669 {
1670         const char *property = g_strdup("SignalBarsChanged");
1671
1672         DBG(" +\n");
1673
1674         if (!__bt_hfp_agent_dbus_method_variant_send(TELEPHONY_CSD_OBJECT_PATH,
1675                         TELEPHONY_CSD_INTERFACE,
1676                         BT_HFP_AGENT_SET_PROPERTY,
1677                         property, DBUS_TYPE_INT32, &signal_bar)) {
1678                 DBG("__bt_hfp_agent_dbus_method_variant_send - ERROR\n");
1679                 g_free((void *)property);
1680                 return FALSE;
1681         }
1682
1683         g_free((void *)property);
1684         DBG(" -\n");
1685         return TRUE;
1686 }
1687
1688 static gboolean __bt_hfp_agent_send_battery_level_changed(int battery_level)
1689 {
1690         const char *property = g_strdup("BatteryBarsChanged");
1691         int battery_status;
1692
1693         DBG(" +\n");
1694
1695         /* We need to send battery status ranging from 0-5 */
1696         if (battery_level < 5)
1697                  battery_status = 0;
1698         else if (battery_level >= 100)
1699                 battery_status = 5;
1700         else
1701                 battery_status = battery_level / 20 + 1;
1702
1703         if (!__bt_hfp_agent_dbus_method_variant_send(TELEPHONY_CSD_OBJECT_PATH,
1704                         TELEPHONY_CSD_INTERFACE,
1705                         BT_HFP_AGENT_SET_PROPERTY,
1706                         property,
1707                         DBUS_TYPE_INT32, &battery_status)) {
1708                 DBG("__bt_hfp_agent_dbus_method_variant_send - ERROR\n");
1709                 g_free((void *)property);
1710                 return FALSE;
1711         }
1712
1713         DBG(" -\n");
1714         g_free((void *)property);
1715         return TRUE;
1716 }
1717
1718 static void __bt_hfp_agent_send_battery_level(void)
1719 {
1720         int ret;
1721         int batt;
1722
1723         DBG(" +\n");
1724
1725         ret = vconf_get_int(VCONFKEY_SYSMAN_BATTERY_CAPACITY, &batt);
1726         if (ret != 0) {
1727                 DBG("vconf_get_int failed err = %d \n", ret);
1728                 return;
1729         }
1730
1731         DBG("Current battery Level = [%d] \n", batt);
1732
1733         __bt_hfp_agent_send_battery_level_changed(batt);
1734
1735         DBG(" -\n");
1736 }
1737
1738 static void __bt_hfp_agent_send_signal_status(void)
1739 {
1740         int ret;
1741         int signal_level;
1742
1743         DBG(" +\n");
1744
1745         ret = vconf_get_int(VCONFKEY_TELEPHONY_RSSI, &signal_level);
1746         if (ret != 0) {
1747                 DBG("vconf_get_int failed err = %d \n", ret);
1748                 return;
1749         }
1750
1751         DBG("Current Signal Level = [%d] \n", signal_level);
1752
1753         __bt_hfp_agent_send_signal_bar_changed(signal_level);
1754
1755         DBG(" -\n");
1756 }
1757
1758 static void __bt_hfp_agent_network_send( int service, int roam_status)
1759 {
1760         int ret;
1761         bt_hfp_agent_network_registration_status_t network_service;
1762
1763         DBG(" +\n");
1764
1765         switch (service) {
1766         case VCONFKEY_TELEPHONY_SVCTYPE_NONE:
1767         case VCONFKEY_TELEPHONY_SVCTYPE_NOSVC:
1768         case VCONFKEY_TELEPHONY_SVCTYPE_SEARCH:
1769                 service = 0;
1770                 break;
1771         default:
1772                 service = 1;
1773                 break;
1774         }
1775
1776         ret = vconf_get_int(VCONFKEY_TELEPHONY_SVC_ROAM, &roam_status);
1777         if (ret != 0) {
1778                 DBG("Get roaming status failed err = %d\n", ret);
1779                 return;
1780         }
1781
1782         if (roam_status == 0 && service == 1)
1783                 network_service = BT_HFP_AGENT_NETWORK_REG_STATUS_HOME;
1784         else if (roam_status == 1 && service == 1)
1785                 network_service = BT_HFP_AGENT_NETWORK_REG_STATUS_ROAMING;
1786         else
1787                 network_service = BT_HFP_AGENT_NETWORK_REG_STATUS_UNKOWN;
1788
1789         DBG("Network service = %d\n", network_service);
1790
1791         __bt_hfp_agent_send_registration_status_changed(network_service);
1792
1793         DBG(" -\n");
1794 }
1795
1796 static void __bt_hfp_agent_send_network_status(void)
1797 {
1798         int ret;
1799         int roam_status;
1800         int service;
1801
1802
1803         DBG(" +\n");
1804
1805         ret = vconf_get_int(VCONFKEY_TELEPHONY_SVC_ROAM, &roam_status);
1806         if (ret != 0) {
1807                 DBG("vconf_get_int failed for \n");
1808                 return;
1809         }
1810
1811         DBG("roam_status  = [%d] \n", roam_status);
1812
1813         ret = vconf_get_int(VCONFKEY_TELEPHONY_SVCTYPE, &service);
1814         if (ret != 0) {
1815                 DBG("vconf_get_int failed\n");
1816                 return;
1817         }
1818
1819         DBG("service  = [%d] \n", service);
1820
1821         __bt_hfp_agent_network_send(service, roam_status);
1822
1823         DBG(" -\n");
1824 }
1825
1826 static void __bt_hfp_agent_send_vconf_values(void)
1827 {
1828         __bt_hfp_agent_send_battery_level();
1829         __bt_hfp_agent_send_signal_status();
1830         __bt_hfp_agent_send_network_status();
1831 }
1832
1833 static void __bt_hfp_agent_battery_status_cb(keynode_t *node)
1834 {
1835         int batt = vconf_keynode_get_int(node);
1836
1837         DBG(" +\n");
1838
1839         DBG("Current Battery Level = [%d] \n", batt);
1840
1841         __bt_hfp_agent_send_battery_level_changed(batt);
1842
1843         DBG(" -\n");
1844 }
1845
1846 static void __bt_hfp_agent_network_signal_status_cb(keynode_t *node)
1847 {
1848         int signal_bar = vconf_keynode_get_int(node);
1849
1850         DBG(" +\n");
1851
1852         DBG("Current Signal Level = [%d] \n", signal_bar);
1853
1854         __bt_hfp_agent_send_signal_bar_changed(signal_bar);
1855
1856         DBG(" -\n");
1857 }
1858
1859 static void __bt_hfp_agent_network_register_status_cb(keynode_t *node)
1860 {
1861         int service = vconf_keynode_get_int(node);
1862         int roam_status;
1863         int ret;
1864
1865         DBG(" +\n");
1866
1867         DBG("Current Signal Level = [%d] \n", service);
1868
1869         ret = vconf_get_int(VCONFKEY_TELEPHONY_SVC_ROAM, &roam_status);
1870         if (ret != 0) {
1871                 DBG("Get roaming status failed err = %d\n", ret);
1872                 return;
1873         }
1874
1875         __bt_hfp_agent_network_send(service, roam_status);
1876
1877         DBG(" -\n");
1878 }
1879
1880 static void __bt_hfp_agent_subscribe_vconf_updates(void)
1881 {
1882         int ret;
1883
1884         DBG(" +\n");
1885
1886         ret = vconf_notify_key_changed(VCONFKEY_SYSMAN_BATTERY_CAPACITY,
1887                                 (void *)__bt_hfp_agent_battery_status_cb, NULL);
1888         if (0 != ret) {
1889                 DBG("Subsrciption to battery status failed err =  [%d]\n", ret);
1890         }
1891
1892         ret = vconf_notify_key_changed(VCONFKEY_TELEPHONY_RSSI,
1893                         (void *)__bt_hfp_agent_network_signal_status_cb, NULL);
1894         if (0 != ret) {
1895                 DBG("Subsrciption to netowrk signal failed err =  [%d]\n", ret);
1896         }
1897
1898         ret = vconf_notify_key_changed(VCONFKEY_TELEPHONY_SVCTYPE,
1899                         (void *)__bt_hfp_agent_network_register_status_cb, NULL);
1900         if (0 != ret) {
1901                 DBG("Subsrciption to network failed err =  [%d]\n", ret);
1902         }
1903
1904         DBG(" -\n");
1905 }
1906
1907 static void __bt_hfp_agent_release_vconf_updates(void)
1908 {
1909         int ret;
1910
1911         DBG(" +\n");
1912
1913         ret = vconf_ignore_key_changed(VCONFKEY_SYSMAN_BATTERY_CAPACITY,
1914                         (vconf_callback_fn)__bt_hfp_agent_battery_status_cb);
1915         if (0 != ret) {
1916                 DBG("vconf_ignore_key_changed failed\n");
1917         }
1918
1919         ret = vconf_ignore_key_changed(VCONFKEY_TELEPHONY_RSSI,
1920                 (vconf_callback_fn)__bt_hfp_agent_network_signal_status_cb);
1921         if (0 != ret) {
1922                 DBG("vconf_ignore_key_changed failed\n");
1923         }
1924
1925         ret = vconf_ignore_key_changed(VCONFKEY_TELEPHONY_SVCTYPE,
1926                 (vconf_callback_fn)__bt_hfp_agent_network_register_status_cb);
1927         if (0 != ret) {
1928                 DBG("vconf_ignore_key_changed failed\n");
1929         }
1930
1931         DBG(" -\n");
1932 }
1933
1934 static void __bt_hfp_agent_dbus_init(BtHfpAgent *agent)
1935 {
1936         GError *error = NULL;
1937         DBusGProxy *bus_proxy = NULL;
1938         guint result;
1939
1940         g_connection = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);
1941         if (error != NULL) {
1942                 ERR("Failed connection to system bus[%s] \n", error->message);
1943                 g_error_free(error);
1944                 return;
1945         }
1946
1947         bus_proxy = dbus_g_proxy_new_for_name(g_connection,
1948                                         DBUS_SERVICE_DBUS,
1949                                         DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS);
1950         if (bus_proxy == NULL) {
1951                 ERR("Failed to get a proxy for D-Bus\n");
1952                 return;
1953         }
1954
1955         if (!dbus_g_proxy_call(bus_proxy, "RequestName", &error, G_TYPE_STRING,
1956                         BT_HFP_SERVICE, G_TYPE_UINT, 0, G_TYPE_INVALID,
1957                         G_TYPE_UINT, &result, G_TYPE_INVALID)) {
1958                 if (error != NULL) {
1959                         ERR("RequestName RPC failed[%s]\n", error->message);
1960                         g_error_free(error);
1961                 }
1962
1963                 g_object_unref(bus_proxy);
1964                 return;
1965         }
1966
1967         DBG("result : %d %d\n", result, DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER);
1968         if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
1969                 ERR("Failed to get the primary well-known name.\n");
1970                 g_object_unref(bus_proxy);
1971                 return;
1972         }
1973
1974         g_object_unref(bus_proxy);
1975
1976         dbus_g_connection_register_g_object(g_connection,
1977                 BT_HFP_SERVICE_OBJECT_PATH, G_OBJECT(agent));
1978
1979         gconn = dbus_g_connection_get_connection(g_connection);
1980         if (gconn == NULL) {
1981                 ERR("Failed to get connection \n");
1982                 return;
1983         }
1984
1985         __bt_hfp_agent_send_vconf_values();
1986         __bt_hfp_agent_subscribe_vconf_updates();
1987 }
1988
1989 static void  __bt_hfp_agent_tel_cb(TapiHandle *handle,
1990                                 int result,
1991                                 void *data,
1992                                 void *user_data)
1993 {
1994         TelSimMsisdnList_t *number;
1995         gchar *subscriber_number;
1996
1997         if (data == NULL)
1998                 return;
1999
2000         number = (TelSimMsisdnList_t *)data;
2001         subscriber_number = g_strdup(number->list[0].num);
2002         __bt_hfp_agent_send_subscriber_number_changed(subscriber_number);
2003         g_free(subscriber_number);
2004 }
2005
2006 static void __bt_hfp_agent_sigterm_handler(int signo)
2007 {
2008         if (gmain_loop) {
2009                 g_main_loop_quit(gmain_loop);
2010         } else {
2011                 DBG("Terminating HFP agent");
2012                 exit(0);
2013         }
2014 }
2015
2016 int main(void)
2017 {
2018         TapiHandle *handle;
2019         BtHfpAgent *bt_hfp_obj = NULL;
2020         struct sigaction sa;
2021         int tapi_result;
2022
2023         DBG("Starting Bluetooth HFP agent");
2024
2025         g_type_init();
2026
2027         memset(&sa, 0, sizeof(sa));
2028         sa.sa_flags = SA_NOCLDSTOP;
2029         sa.sa_handler = __bt_hfp_agent_sigterm_handler;
2030         sigaction(SIGTERM, &sa, NULL);
2031         sigaction(SIGINT, &sa, NULL);
2032
2033         gmain_loop = g_main_loop_new(NULL, FALSE);
2034
2035         if (gmain_loop == NULL) {
2036                 ERR("GMainLoop create failed \n");
2037                 return EXIT_FAILURE;
2038         }
2039
2040         bt_hfp_obj = g_object_new(BT_HFP_TYPE_AGENT, NULL);
2041         if (bt_hfp_obj == NULL) {
2042                 ERR("Failed to create BtHfpAgent instance \n");
2043                 if (gmain_loop)
2044                         g_main_loop_unref(gmain_loop);
2045
2046                 return EXIT_FAILURE;
2047         }
2048
2049         handle = tel_init(NULL);
2050         tapi_result = tel_get_sim_msisdn(handle, __bt_hfp_agent_tel_cb,
2051                                         bt_hfp_obj);
2052
2053         if(tapi_result != TAPI_API_SUCCESS)
2054                 ERR("Fail to get sim info: %d", tapi_result);
2055
2056         __bt_hfp_agent_dbus_init(bt_hfp_obj);
2057
2058         g_main_loop_run(gmain_loop);
2059
2060         tel_deinit(handle);
2061
2062         __bt_hfp_agent_release_vconf_updates();
2063
2064         if (bt_hfp_obj) {
2065                 dbus_g_connection_unregister_g_object(g_connection,
2066                                                 G_OBJECT(bt_hfp_obj));
2067                 g_object_unref(bt_hfp_obj);
2068         }
2069
2070         if (g_connection)
2071                 dbus_g_connection_unref(g_connection);
2072
2073         if (gmain_loop)
2074                 g_main_loop_unref(gmain_loop);
2075
2076         DBG("Terminating Bluetooth HFP agent");
2077         return 0;
2078 }