Apply tizen 3.0 based product patchsets
[platform/core/connectivity/bluetooth-agent.git] / pb-agent / bluetooth_pb_agent.c
1 /*
2  * Bluetooth-agent
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact:  Hocheol Seo <hocheol.seo@samsung.com>
7  *               Girishashok Joshi <girish.joshi@samsung.com>
8  *               Chanyeol Park <chanyeol.park@samsung.com>
9  *               Jaekyun Lee <jkyun.leek@samsung.com>
10  *
11  * Licensed under the Apache License, Version 2.0 (the "License");
12  * you may not use this file except in compliance with the License.
13  * You may obtain a copy of the License at
14  *
15  *              http://www.apache.org/licenses/LICENSE-2.0
16  *
17  * Unless required by applicable law or agreed to in writing, software
18  * distributed under the License is distributed on an "AS IS" BASIS,
19  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20  * See the License for the specific language governing permissions and
21  * limitations under the License.
22  *
23  */
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <unistd.h>
29 #include <signal.h>
30 #include <glib.h>
31 #include <gio/gio.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <fcntl.h>
35 #include <contacts.h>
36 #include <TapiUtility.h>
37 #include <ITapiSim.h>
38
39 #include "bluetooth_pb_agent.h"
40 #include "bluetooth_pb_vcard.h"
41
42 #define BLUETOOTH_PB_AGENT_TIMEOUT 600
43
44 typedef struct {
45         TapiHandle *tapi_handle;
46         gchar *tel_number;
47         guint timeout_id;
48         PhoneBookType pb_type;
49         guint pbagent_interface_id;
50         guint pbagent_at_interface_id;
51 } PbAgentData;
52
53 static gchar *bluetooth_pb_agent_folder_list[] = {
54         "/telecom/pb",
55         "/telecom/ich",
56         "/telecom/och",
57         "/telecom/mch",
58         "/telecom/cch",
59 #ifdef TIZEN_FEATURE_BT_PBAP_SIM
60         "/SIM1/telecom/pb",
61 #endif
62         NULL
63 };
64
65 static guint total_missed_call_count = 0;
66 static guint unnotified_missed_call_count = 0;
67
68 GMainLoop *g_mainloop;
69 static GDBusConnection *pb_dbus_conn = NULL;
70
71 static const gchar pb_agent_introspection_xml[] =
72 "<node name='/'>"
73         "<interface name='org.bluez.PbAgent'>"
74                 "<method name='GetPhonebookFolderList'>"
75                         "<arg type='as' name='folder_list' direction='out'/>"
76                 "</method>"
77
78                 "<method name='GetPhonebook'>"
79                         "<arg type='s' name='name'/>"
80                         "<arg type='t' name='filter'/>"
81                         "<arg type='y' name='format'/>"
82                         "<arg type='q' name='max_list_count'/>"
83                         "<arg type='q' name='list_start_offset'/>"
84                         "<arg type='as' name='phonebook' direction='out'/>"
85                         "<arg type='u' name='new_missed_call' direction='out'/>"
86                 "</method>"
87
88                 "<method name='GetPhonebookSize'>"
89                         "<arg type='s' name='name'/>"
90                         "<arg type='u' name='phonebook_size' direction='out'/>"
91                         "<arg type='u' name='new_missed_call' direction='out'/>"
92                 "</method>"
93
94                 "<method name='GetPhonebookList'>"
95                         "<arg type='s' name='name'/>"
96                         "<arg type='a(ssu)' name='phonebook_list' direction='out'/>"
97                         "<arg type='u' name='new_missed_call' direction='out'/>"
98                 "</method>"
99
100                 "<method name='GetPhonebookEntry'>"
101                         "<arg type='s' name='folder'/>"
102                         "<arg type='s' name='id'/>"
103                         "<arg type='t' name='filter'/>"
104                         "<arg type='y' name='format'/>"
105                         "<arg type='s' name='phonebook_entry' direction='out'/>"
106                 "</method>"
107
108                 "<method name='GetTotalObjectCount'>"
109                         "<arg type='s' name='path'/>"
110                         "<arg type='u' name='phonebook_size' direction='out'/>"
111                 "</method>"
112
113                 "<method name='AddContact'>"
114                         "<arg type='s' name='filename'/>"
115                 "</method>"
116
117                 "<method name='DestroyAgent'>"
118                 "</method>"
119         "</interface>"
120
121         "<interface name='org.bluez.PbAgent.At'>"
122                 "<method name='GetPhonebookSizeAt'>"
123                         "<arg type='s' name='command'/>"
124                         "<arg type='u' name='phonebook_size' direction='out'/>"
125                 "</method>"
126
127                 "<method name='GetPhonebookEntriesAt'>"
128                         "<arg type='s' name='command'/>"
129                         "<arg type='i' name='start_index'/>"
130                         "<arg type='i' name='end_index'/>"
131                         "<arg type='a(ssu)' name='phonebook_entries' direction='out'/>"
132                 "</method>"
133
134                 "<method name='GetPhonebookEntriesFindAt'>"
135                         "<arg type='s' name='command'/>"
136                         "<arg type='s' name='find_text' />"
137                         "<arg type='a(ssu)' name='phonebook_entries' direction='out'/>"
138                 "</method>"
139         "</interface>"
140 "</node>";
141
142 static void __bt_pb_agent_method(GDBusConnection *connection,
143                         const gchar *sender, const gchar *object_path,
144                         const gchar *interface_name, const gchar *method_name,
145                         GVariant *parameters, GDBusMethodInvocation *invocation,
146                         gpointer user_data);
147
148 static GVariant *__bt_pb_get_phonebook_folder_list(GError **error);
149
150 static GVariant *__bt_pb_get_phonebook(PbAgentData *agent, const char *name,
151                         guint64 filter, guint8 format, guint16 max_list_count,
152                         guint16 list_start_offset, GError **err);
153
154 static GVariant *__bt_pb_get_phonebook_size(PbAgentData *agent,
155                                         const char *name, GError **err);
156
157 static GVariant *__bt_pb_get_phonebook_list(PbAgentData *agent,
158                                         const char *name, GError **err);
159
160 static GVariant *__bt_pb_get_phonebook_entry(PbAgentData *agent,
161                         const gchar *folder, const gchar *id, guint64 filter,
162                         guint8 format, GError **err);
163
164 static GVariant *__bt_pb_get_phonebook_size_at(PbAgentData *agent,
165                                         const gchar *command, GError **err);
166
167 static GVariant *__bt_pb_get_phonebook_entries_at(PbAgentData *agent,
168                         const gchar *command, gint32 start_index,
169                         gint32 end_index, GError **err);
170
171 static GVariant *__bt_pb_get_phonebook_entries_find_at(PbAgentData *agent,
172                                 const gchar *command, const gchar *find_text,
173                                 GError **err);
174
175 static GVariant *__bt_pb_get_total_object_count(PbAgentData *agent,
176                                         gchar *path, GError **err);
177
178 static gboolean __bt_pb_add_contact(PbAgentData *agent, const char *filename,
179                                         GError **error);
180
181 static gboolean __bt_pb_destroy_agent();
182
183 static GError *__bt_pb_error(gint error_code, const gchar *error_message);
184
185 static PhoneBookType __bluetooth_pb_get_pb_type(const char *name);
186
187 static PhoneBookType __bluetooth_pb_get_storage_pb_type(const char *name);
188
189 static gint __bluetooth_pb_phone_log_filter_append(contacts_filter_h filter,
190                                                 gint *match, gint size);
191
192 static contacts_query_h __bluetooth_pb_query_phone_log(gint *match, gint size);
193
194 static contacts_query_h __bluetooth_pb_query_person(int addressbook);
195
196 static contacts_query_h __bluetooth_pb_query_person_number(void);
197
198 static contacts_query_h __bluetooth_pb_query_phone_log_incoming(void);
199
200 static contacts_query_h __bluetooth_pb_query_phone_log_outgoing(void);
201
202 static contacts_query_h __bluetooth_pb_query_phone_log_missed(void);
203
204 static contacts_query_h __bluetooth_pb_query_phone_log_combined(void);
205
206 static gboolean __bluetooth_pb_get_count(PhoneBookType pb_type, guint *count);
207
208 static gboolean __bluetooth_pb_get_count_new_missed_call(guint *count);
209
210 static const char *__bluetooth_pb_phone_log_get_log_type(contacts_record_h record);
211
212 static void __bluetooth_pb_get_vcards(PbAgentData *agent, PhoneBookType pb_type,
213                         guint64 filter, guint8 format, guint16 max_list_count,
214                         guint16 list_start_offset, GVariantBuilder *vcards);
215
216 static void __bluetooth_pb_get_contact_list(PbAgentData *agent,
217                         contacts_query_h query, GVariantBuilder *builder);
218
219 static void __bluetooth_pb_get_phone_log_list(PbAgentData *agent,
220                         contacts_query_h query, GVariantBuilder *builder);
221
222 static void __bluetooth_pb_get_list(PbAgentData *agent, PhoneBookType pb_type,
223                                 GVariantBuilder *builder);
224
225 static void __bluetooth_pb_get_contact_list_number(PbAgentData *agent,
226                                 contacts_query_h query, gint start_index,
227                                 gint end_index, GVariantBuilder *builder);
228
229 static void __bluetooth_pb_get_phone_log_list_number(PbAgentData *agent,
230                                 contacts_query_h query, gint start_index,
231                                 gint end_index, GVariantBuilder *builder);
232
233 static void __bluetooth_pb_get_list_number(PbAgentData *agent,
234                                 PhoneBookType pb_type, gint start_index,
235                                 gint end_index, GVariantBuilder *builder);
236
237 static void __bluetooth_pb_get_contact_list_name(PbAgentData *agent,
238                                 contacts_query_h query, const gchar *find_text,
239                                 GVariantBuilder *builder);
240
241 static void __bluetooth_pb_get_phone_log_list_name(PbAgentData *agent,
242                                 contacts_query_h query, const gchar *find_text,
243                                 GVariantBuilder *builder);
244
245 static void __bluetooth_pb_get_list_name(PbAgentData *agent,
246                                 PhoneBookType pb_type, const gchar *find_text,
247                                 GVariantBuilder *builder);
248
249 static void __bluetooth_pb_list_ptr_array_add(GVariantBuilder *builder,
250                         const gchar *name, const gchar *number, gint handle);
251
252 static void __bluetooth_pb_agent_signal_handler(int signum);
253
254 static void __bluetooth_pb_contact_changed(const gchar *view_uri,
255                                         void *user_data);
256
257 static void __bluetooth_pb_agent_timeout_add_seconds(PbAgentData *agent);
258
259 static gboolean __bluetooth_pb_agent_timeout_calback(gpointer user_data);
260
261 static void __bluetooth_pb_tel_callback(TapiHandle *handle, int result,
262                                         void *data, void *user_data);
263
264 static gboolean __bt_pb_dbus_init(PbAgentData *agent);
265
266 static gboolean __bt_pb_dbus_deinit(PbAgentData *agent);
267
268 static const GDBusInterfaceVTable method_table = {
269         __bt_pb_agent_method,
270         NULL,
271         NULL,
272 };
273
274 static void __bt_pb_agent_method(GDBusConnection *connection,
275                         const gchar *sender, const gchar *object_path,
276                         const gchar *interface_name, const gchar *method_name,
277                         GVariant *parameters, GDBusMethodInvocation *invocation,
278                         gpointer user_data)
279 {
280         FN_START;
281         INFO("method: %s; object_path: %s", method_name, object_path);
282         PbAgentData *agent = (PbAgentData *)user_data;
283         GError *err = NULL;
284         if (g_strcmp0(interface_name, "org.bluez.PbAgent") == 0) {
285                 if (g_strcmp0(method_name, "GetPhonebookFolderList") == 0) {
286                         GVariant *folder_list = NULL;
287
288                         folder_list = __bt_pb_get_phonebook_folder_list(&err);
289                         if (err)
290                                 goto fail;
291                         g_dbus_method_invocation_return_value(invocation,
292                                                                 folder_list);
293                 } else if (g_strcmp0(method_name, "GetPhonebook") == 0) {
294                         GVariant *phonebook = NULL;
295                         const char *name;
296                         guint64 filter;
297                         guint8 format;
298                         guint16 max_list_count;
299                         guint16 list_start_offset;
300
301                         g_variant_get(parameters, "(&styqq)", &name, &filter,
302                                                 &format, &max_list_count,
303                                                 &list_start_offset);
304                         phonebook = __bt_pb_get_phonebook(agent, name, filter,
305                                                 format, max_list_count,
306                                                 list_start_offset, &err);
307                         if (err)
308                                 goto fail;
309                         g_dbus_method_invocation_return_value(invocation,
310                                                                 phonebook);
311                 } else if (g_strcmp0(method_name, "GetPhonebookSize") == 0) {
312                         GVariant *phonebook_size = NULL;
313                         const char *name;
314
315                         g_variant_get(parameters, "(&s)", &name);
316                         phonebook_size = __bt_pb_get_phonebook_size(agent, name,
317                                                                         &err);
318                         if (err)
319                                 goto fail;
320                         g_dbus_method_invocation_return_value(invocation,
321                                                                 phonebook_size);
322                 } else if (g_strcmp0(method_name, "GetPhonebookList") == 0) {
323                         GVariant *phonebook_list = NULL;
324                         const char *name;
325
326                         g_variant_get(parameters, "(&s)", &name);
327                         phonebook_list = __bt_pb_get_phonebook_list(agent, name,
328                                                                         &err);
329                         if (err)
330                                 goto fail;
331                         g_dbus_method_invocation_return_value(invocation,
332                                                                 phonebook_list);
333                 } else if (g_strcmp0(method_name, "GetPhonebookEntry") == 0) {
334                         GVariant *phonebook_entry = NULL;
335                         const gchar *folder;
336                         const gchar *id;
337                         guint64 filter;
338                         guint8 format;
339
340                         g_variant_get(parameters, "(&s&sty)", &folder, &id,
341                                                         &filter, &format);
342                         phonebook_entry = __bt_pb_get_phonebook_entry(agent,
343                                                 folder, id, filter, format, &err);
344                         if (err)
345                                 goto fail;
346                         g_dbus_method_invocation_return_value(invocation,
347                                                         phonebook_entry);
348                 } else if (g_strcmp0(method_name, "GetTotalObjectCount") == 0) {
349                         GVariant *phonebook_size = NULL;
350                         gchar *path;
351
352                         g_variant_get(parameters, "(&s)", &path);
353                         phonebook_size = __bt_pb_get_total_object_count(agent,
354                                                                 path, &err);
355                         if (err)
356                                 goto fail;
357                         g_dbus_method_invocation_return_value(invocation,
358                                                                 phonebook_size);
359                 } else if (g_strcmp0(method_name, "AddContact") == 0) {
360                         const char *filename;
361
362                         g_variant_get(parameters, "(&s)", &filename);
363                         __bt_pb_add_contact(agent, filename, &err);
364                         if (err)
365                                 goto fail;
366                         g_dbus_method_invocation_return_value(invocation, NULL);
367                 } else if (g_strcmp0(method_name, "DestroyAgent") == 0) {
368                         g_dbus_method_invocation_return_value(invocation, NULL);
369                         __bt_pb_destroy_agent();
370                 }
371         } else if (g_strcmp0(interface_name, "org.bluez.PbAgent.At") == 0) {
372                 if (g_strcmp0(method_name, "GetPhonebookSizeAt") == 0) {
373                         GVariant *phonebook_size = NULL;
374                         const gchar *command;
375
376                         g_variant_get(parameters, "(&s)", &command);
377                         phonebook_size = __bt_pb_get_phonebook_size_at(agent,
378                                                                 command, &err);
379                         if (err)
380                                 goto fail;
381                         g_dbus_method_invocation_return_value(invocation,
382                                                                 phonebook_size);
383                 } else if (g_strcmp0(method_name,
384                                         "GetPhonebookEntriesAt") == 0) {
385                         GVariant *phonebook_entries = NULL;
386                         const gchar *command;
387                         gint32 start_index;
388                         gint32 end_index;
389
390                         g_variant_get(parameters, "(&sii)",
391                                         &command, &start_index, &end_index);
392                         phonebook_entries = __bt_pb_get_phonebook_entries_at(agent,
393                                                         command, start_index,
394                                                         end_index, &err);
395                         if (err)
396                                 goto fail;
397                         g_dbus_method_invocation_return_value(invocation,
398                                                         phonebook_entries);
399                 } else if (g_strcmp0(method_name,
400                                         "GetPhonebookEntriesFindAt") == 0) {
401                         GVariant *phonebook_entries = NULL;
402                         const gchar *command;
403                         const gchar *find_text;
404
405                         g_variant_get(parameters, "(&s&s)", &command, &find_text);
406                         phonebook_entries = __bt_pb_get_phonebook_entries_find_at(agent,
407                                                         command, find_text, &err);
408                         if (err)
409                                 goto fail;
410                         g_dbus_method_invocation_return_value(invocation,
411                                                         phonebook_entries);
412                 }
413         }
414
415         FN_END;
416         return;
417
418 fail:
419         g_dbus_method_invocation_return_gerror(invocation, err);
420         g_clear_error(&err);
421         FN_END;
422         return;
423 }
424
425 static void bluetooth_pb_agent_clear(PbAgentData *agent)
426 {
427         FN_START;
428         agent->pb_type = TELECOM_NONE;
429         FN_END;
430 }
431
432 static GDBusConnection *__bt_pb_get_gdbus_connection(void)
433 {
434         FN_START;
435         GError *err = NULL;
436
437         if (pb_dbus_conn)
438                 return pb_dbus_conn;
439
440         pb_dbus_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
441         if (!pb_dbus_conn) {
442                 if (err) {
443                         ERR("Unable to connect to dbus: %s", err->message);
444                         g_clear_error(&err);
445                 }
446                 return NULL;
447         }
448         FN_END;
449         return pb_dbus_conn;
450 }
451
452 static GVariant *__bt_pb_get_phonebook_folder_list(GError **error)
453 {
454         FN_START;
455         GVariant *folder_list;
456         gint size;
457         gint i;
458         GVariantBuilder *builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
459
460         size = G_N_ELEMENTS(bluetooth_pb_agent_folder_list);
461
462         for (i = 0; i < size; i++)
463                 g_variant_builder_add(builder, "s",
464                                         bluetooth_pb_agent_folder_list[i]);
465
466         folder_list = g_variant_new("(as)", builder);
467         g_variant_builder_unref(builder);
468
469         FN_END;
470         return folder_list;
471 }
472
473
474 static GVariant *__bt_pb_get_phonebook(PbAgentData *agent, const char *name,
475                         guint64 filter, guint8 format, guint16 max_list_count,
476                         guint16 list_start_offset, GError **err)
477 {
478         FN_START;
479         GVariant *phonebook;
480         PhoneBookType pb_type = TELECOM_NONE;
481         GVariantBuilder *vcards;
482
483         INFO("name: %s filter: %lld format: %d max_list_count: %d list_start_offset: %d\n",
484                         name, filter, format, max_list_count, list_start_offset);
485
486         __bluetooth_pb_agent_timeout_add_seconds(agent);
487
488         pb_type = __bluetooth_pb_get_pb_type(name);
489
490         if (pb_type == TELECOM_NONE) {
491                 *err = __bt_pb_error(G_FILE_ERROR_INVAL,
492                                                 "unsupported name defined");
493                 return NULL;
494         }
495
496         vcards = g_variant_builder_new(G_VARIANT_TYPE("as"));
497
498         if (max_list_count > 0) {
499                 __bluetooth_pb_get_vcards(agent, pb_type, filter, format,
500                                 max_list_count, list_start_offset, vcards);
501         }
502
503         if (pb_type == TELECOM_MCH) {
504                 phonebook = g_variant_new("(asu)", vcards,
505                                                 unnotified_missed_call_count);
506                 INFO("Notified [%d] missed call count",
507                                                 unnotified_missed_call_count);
508                 unnotified_missed_call_count = 0;
509         } else {
510                 phonebook = g_variant_new("(asu)", vcards, 0);
511         }
512
513         g_variant_builder_unref(vcards);
514
515         FN_END;
516         return phonebook;
517 }
518
519 static GVariant *__bt_pb_get_phonebook_size(PbAgentData *agent,
520                                                 const char *name, GError **err)
521 {
522         FN_START;
523         GVariant *phonebook_size;
524         PhoneBookType pb_type = TELECOM_NONE;
525         guint count = 0;
526
527         DBG_SECURE("name: %s\n", name);
528
529         __bluetooth_pb_agent_timeout_add_seconds(agent);
530
531         pb_type = __bluetooth_pb_get_pb_type(name);
532
533         if (__bluetooth_pb_get_count(pb_type, &count) == FALSE) {
534                 *err = __bt_pb_error(G_FILE_ERROR_INVAL,
535                                                 "unsupported name defined");
536                 return NULL;
537         }
538
539         /* for owner */
540 #ifdef TIZEN_FEATURE_BT_PBAP_SIM
541         if (pb_type == TELECOM_PB || pb_type == SIM_PB)
542                 count++;
543 #else
544         if (pb_type == TELECOM_PB)
545                 count++;
546 #endif
547         if (pb_type == TELECOM_MCH) {
548                 phonebook_size = g_variant_new("(uu)", count,
549                                                 unnotified_missed_call_count);
550                 INFO("Notified [%d] missed call count",
551                                                 unnotified_missed_call_count);
552                 unnotified_missed_call_count = 0;
553         } else {
554                 phonebook_size = g_variant_new("(uu)", count, 0);
555         }
556
557         FN_END;
558         return phonebook_size;
559 }
560
561
562 static GVariant *__bt_pb_get_phonebook_list(PbAgentData *agent,
563                                                 const char *name, GError **err)
564 {
565         FN_START;
566         GVariant *phonebook_list;
567         PhoneBookType pb_type = TELECOM_NONE;
568
569         GVariantBuilder *builder;
570
571         DBG_SECURE("name: %s\n", name);
572
573         __bluetooth_pb_agent_timeout_add_seconds(agent);
574
575         pb_type = __bluetooth_pb_get_pb_type(name);
576
577         if (pb_type == TELECOM_NONE) {
578                 *err = __bt_pb_error(G_FILE_ERROR_INVAL,
579                                                 "unsupported name defined");
580                 return NULL;
581         }
582
583         builder = g_variant_builder_new(G_VARIANT_TYPE("a(ssu)"));
584
585         __bluetooth_pb_get_list(agent, pb_type, builder);
586
587         INFO("pb_type[%d] / number of missed_call[%d]", pb_type,
588                                                 unnotified_missed_call_count);
589
590         if (pb_type == TELECOM_MCH) {
591                 phonebook_list = g_variant_new("(a(ssu)u)", builder,
592                                                 unnotified_missed_call_count);
593                 INFO("Notified [%d] missed call count",
594                                                 unnotified_missed_call_count);
595                 unnotified_missed_call_count = 0;
596         } else {
597                 phonebook_list = g_variant_new("(a(ssu)u)", builder, 0);
598         }
599
600         g_variant_builder_unref(builder);
601
602         FN_END;
603         return phonebook_list;
604 }
605
606 static GVariant *__bt_pb_get_phonebook_entry(PbAgentData *agent,
607                         const gchar *folder, const gchar *id, guint64 filter,
608                         guint8 format, GError **err)
609 {
610         FN_START;
611         GVariant *phonebook_entry;
612         PhoneBookType pb_type = TELECOM_NONE;
613         gint handle = 0;
614         gchar *str = NULL;
615         const gchar *attr = NULL;
616
617         DBG_SECURE("folder: %s id: %s filter: %ld format: %d\n",
618                         folder, id, filter, format);
619
620         __bluetooth_pb_agent_timeout_add_seconds(agent);
621
622         if (!g_str_has_suffix(id, ".vcf")) {
623                 *err = __bt_pb_error(G_FILE_ERROR_INVAL, "invalid vcf file");
624                 return NULL;
625         }
626
627         handle = (gint)g_ascii_strtoll(id, NULL, 10);
628
629         pb_type = __bluetooth_pb_get_pb_type(folder);
630
631         if (pb_type == TELECOM_NONE) {
632                 *err = __bt_pb_error(G_FILE_ERROR_INVAL,
633                                                 "unsupported name defined");
634                 return NULL;
635         }
636
637         /* create index cache */
638         __bluetooth_pb_get_list(agent, pb_type, NULL);
639
640         switch (pb_type) {
641         case TELECOM_PB:
642                 if (handle == 0) {
643                         str = _bluetooth_pb_vcard_contact_owner(agent->tel_number,
644                                                                 filter, format);
645                 } else {
646                         if (_bluetooth_get_contact_addressbook(handle) == PBAP_ADDRESSBOOK_PHONE)
647                                 str = _bluetooth_pb_vcard_contact(handle,
648                                                                 filter, format);
649                 }
650                 break;
651
652         case TELECOM_ICH:
653                 str = _bluetooth_pb_vcard_call(handle, filter, format,
654                                                                 "RECEIVED");
655                 break;
656         case TELECOM_OCH:
657                 str = _bluetooth_pb_vcard_call(handle, filter, format, "DIALED");
658                 break;
659         case TELECOM_MCH:
660                 str = _bluetooth_pb_vcard_call(handle, filter, format, "MISSED");
661                 break;
662         case TELECOM_CCH: {
663                 contacts_record_h record = NULL;
664
665                 gint status;
666
667                 status = contacts_db_get_record(_contacts_phone_log._uri,
668                                 handle, &record);
669
670                 if (status != CONTACTS_ERROR_NONE)
671                         break;
672
673                 attr = __bluetooth_pb_phone_log_get_log_type(record);
674                 str = _bluetooth_pb_vcard_call(handle, filter, format, attr);
675
676                 contacts_record_destroy(record, TRUE);
677                 break;
678         }
679 #ifdef TIZEN_FEATURE_BT_PBAP_SIM
680         case SIM_PB:
681                 if (handle == 0) {
682                         str = _bluetooth_pb_vcard_contact_owner(agent->tel_number,
683                                                                 filter, format);
684                 } else {
685                         if (_bluetooth_get_contact_addressbook(handle) == PBAP_ADDRESSBOOK_SIM)
686                                 str = _bluetooth_pb_vcard_contact(handle,
687                                                                 filter, format);
688                 }
689                 break;
690 #endif
691         default:
692                 *err = __bt_pb_error(G_FILE_ERROR_INVAL,
693                                                 "unsupported name defined");
694                 return NULL;
695         }
696
697         phonebook_entry = g_variant_new("(s)", str);
698
699         g_free(str);
700
701         FN_END;
702         return phonebook_entry;
703 }
704
705 static GVariant *__bt_pb_get_phonebook_size_at(PbAgentData *agent,
706                                         const gchar *command, GError **err)
707 {
708         FN_START;
709         GVariant *phonebook_size;
710         PhoneBookType pb_type = TELECOM_NONE;
711         guint count = 0;
712
713         DBG("command: %s\n", command);
714
715         __bluetooth_pb_agent_timeout_add_seconds(agent);
716
717         pb_type = __bluetooth_pb_get_storage_pb_type(command);
718
719         if (__bluetooth_pb_get_count(pb_type, &count) == FALSE) {
720                 *err = __bt_pb_error(G_FILE_ERROR_INVAL,
721                                                 "unsupported name defined");
722                 return NULL;
723         }
724
725         phonebook_size = g_variant_new("(u)", count);
726
727         FN_END;
728         return phonebook_size;
729 }
730
731 static GVariant *__bt_pb_get_phonebook_entries_at(PbAgentData *agent,
732                                 const gchar *command, gint32 start_index,
733                                 gint32 end_index, GError **err)
734 {
735         FN_START;
736         GVariant *phonebook_entries;
737         PhoneBookType pb_type = TELECOM_NONE;
738         GVariantBuilder *builder;
739
740         DBG("command: %s, start_index: %d, end_index: %d\n",
741                         command, start_index, end_index);
742
743         __bluetooth_pb_agent_timeout_add_seconds(agent);
744
745         pb_type = __bluetooth_pb_get_storage_pb_type(command);
746
747         if (pb_type == TELECOM_NONE || pb_type == TELECOM_CCH) {
748                 *err = __bt_pb_error(G_FILE_ERROR_INVAL,
749                                                 "unsupported name defined");
750                 return NULL;
751         }
752
753         builder = g_variant_builder_new(G_VARIANT_TYPE("a(ssu)"));
754
755         __bluetooth_pb_get_list_number(agent, pb_type,
756                         start_index, end_index, builder);
757
758         phonebook_entries = g_variant_new("(a(ssu))", builder);
759         g_variant_builder_unref(builder);
760
761         FN_END;
762         return phonebook_entries;
763 }
764
765 static GVariant *__bt_pb_get_phonebook_entries_find_at(PbAgentData *agent,
766                                 const gchar *command, const gchar *find_text,
767                                 GError **err)
768 {
769         FN_START;
770         GVariant *phonebook_entries;
771         PhoneBookType pb_type = TELECOM_NONE;
772         GVariantBuilder *builder;
773
774         DBG("command: %s, find text: %s\n", command, find_text);
775
776         __bluetooth_pb_agent_timeout_add_seconds(agent);
777
778         pb_type = __bluetooth_pb_get_storage_pb_type(command);
779
780         if (pb_type == TELECOM_NONE || pb_type == TELECOM_CCH) {
781                 *err = __bt_pb_error(G_FILE_ERROR_INVAL,
782                                                 "unsupported name defined");
783                 return NULL;
784         }
785
786         builder = g_variant_builder_new(G_VARIANT_TYPE("a(ssu)"));
787
788         __bluetooth_pb_get_list_name(agent, pb_type, find_text, builder);
789
790         phonebook_entries = g_variant_new("(a(ssu))", builder);
791
792         g_variant_builder_unref(builder);
793
794         FN_END;
795         return phonebook_entries;
796 }
797
798 static GVariant *__bt_pb_get_total_object_count(PbAgentData *agent,
799                                                 gchar *path, GError **err)
800 {
801         FN_START;
802         GVariant *phonebook_size;
803         guint count = 0;
804         PhoneBookType pb_type = TELECOM_NONE;
805
806         __bluetooth_pb_agent_timeout_add_seconds(agent);
807
808         pb_type = __bluetooth_pb_get_storage_pb_type(path);
809
810         if (__bluetooth_pb_get_count(pb_type, &count) == FALSE) {
811                 *err = __bt_pb_error(G_FILE_ERROR_INVAL,
812                                                 "unsupported name defined");
813                 return NULL;
814         }
815
816         phonebook_size = g_variant_new("(u)", count);
817
818         FN_END;
819         return phonebook_size;
820 }
821
822 #if 0
823 static int __bluetooth_pb_agent_read_file(const char *file_path, char **stream)
824 {
825         FN_START;
826         FILE *fp = NULL;
827         int read_len = -1;
828         int received_file_size = 0;
829         struct stat file_attr;
830
831         if (file_path == NULL || stream == NULL) {
832                 ERR("Invalid data \n");
833                 return -1;
834         }
835
836         DBG_SECURE("file_path = %s\n", file_path);
837
838         if ((fp = fopen(file_path, "r+")) == NULL) {
839                 ERR_SECURE("Cannot open %s\n", file_path);
840                 return -1;
841         }
842
843         if (fstat(fileno(fp), &file_attr) == 0) {
844                 received_file_size = file_attr.st_size;
845                 DBG("file_attr.st_size = %d, size = %d\n", file_attr.st_size,
846                                                         received_file_size);
847
848                 if (received_file_size <= 0) {
849                         ERR_SECURE("Some problem in the file size [%s]  \n",
850                                                                 file_path);
851                         fclose(fp);
852                         fp = NULL;
853                         return -1;
854                 }
855
856                 *stream = (char *)malloc(sizeof(char) *received_file_size);
857                 if (NULL == *stream) {
858                         fclose(fp);
859                         fp = NULL;
860                         return -1;
861                 }
862         } else {
863                 ERR_SECURE("Some problem in the file [%s]  \n", file_path);
864                 fclose(fp);
865                 fp = NULL;
866                 return -1;
867         }
868
869         read_len = fread(*stream, 1, received_file_size, fp);
870
871         if (read_len == 0) {
872                 if (fp != NULL) {
873                         fclose(fp);
874                         fp = NULL;
875                 }
876                 DBG_SECURE("Cannot open %s\n", file_path);
877                 return -1;
878         }
879
880         if (fp != NULL) {
881                 fclose(fp);
882                 fp = NULL;
883         }
884         FN_END;
885         return 0;
886 }
887 #endif
888
889 static gboolean __bt_pb_add_contact(PbAgentData *agent, const char *filename,
890                                          GError **error)
891 {
892         FN_START;
893         /* Contact API is changed, Temporary blocked */
894 #if 0
895         CTSstruct *contact_record = NULL;
896         GSList *numbers_list = NULL, *cursor;
897         int is_success = 0;
898         int is_duplicated = 0;
899         int err = 0;
900         char *stream = NULL;
901
902         DBG_SECURE("file_path = %s\n", filename);
903
904         err = contacts_svc_connect();
905         ERR("contact_db_service_connect fucntion call [error] = %d \n", err);
906
907         err = __bluetooth_pb_agent_read_file(filename, &stream);
908
909         if (err != 0) {
910                 contacts_svc_disconnect();
911                 ERR("contacts_svc_disconnect fucntion call [error] = %d \n", err);
912
913                 if (NULL != stream) {
914                         free(stream);
915                         stream = NULL;
916                 }
917                 return FALSE;
918         }
919
920         is_success = contacts_svc_get_contact_from_vcard((const void *)stream,
921                                                         &contact_record);
922
923         DBG("contacts_svc_get_contact_from_vcard fucntion call [is_success] = %d \n", is_success);
924
925         if (0 == is_success) {
926                 contacts_svc_struct_get_list(contact_record, CTS_CF_NUMBER_LIST,
927                                                                 &numbers_list);
928                 cursor = numbers_list;
929
930                 for (; cursor; cursor = g_slist_next(cursor)) {
931                         if (contacts_svc_find_contact_by(CTS_FIND_BY_NUMBER,
932                                         contacts_svc_value_get_str(cursor->data,
933                                         CTS_NUM_VAL_NUMBER_STR)) > 0) {
934                                 DBG("is_duplicated\n");
935                                 is_duplicated = TRUE;
936                         }
937                 }
938
939                 if (is_duplicated == FALSE)
940                         contacts_svc_insert_contact(0, contact_record);
941         } else {
942                 ERR("Fail \n");
943         }
944
945         err = contacts_svc_disconnect();
946         ERR("contacts_svc_disconnect fucntion call [error] = %d \n", err);
947
948         if (NULL != stream) {
949                 free(stream);
950                 stream = NULL;
951         }
952 #endif
953         FN_END;
954         return TRUE;
955 }
956
957 /* Create GError from error code and error message*/
958 static GError *__bt_pb_error(gint error_code, const gchar *error_message)
959 {
960         return g_error_new(g_quark_from_string("PB Agent"),
961                         error_code, "PB Agent Error: %s", error_message);
962 }
963
964 static PhoneBookType __bluetooth_pb_get_pb_type(const char *name)
965 {
966         FN_START;
967         gchar *suffix = ".vcf";
968         gint len;
969         gint size;
970         gint i;
971
972         if (name == NULL)
973                 return TELECOM_NONE;
974
975         len = strlen(name);
976
977         if (g_str_has_suffix(name, suffix))
978                 len -= strlen(suffix);
979
980         size = G_N_ELEMENTS(bluetooth_pb_agent_folder_list) - 1;
981         for (i = 0; i < size; i++) {
982                 if (strncmp(name, bluetooth_pb_agent_folder_list[i], len) == 0)
983                         return i;
984         }
985
986         FN_END;
987         return TELECOM_NONE;
988 }
989
990 static PhoneBookType __bluetooth_pb_get_storage_pb_type(const char *name)
991 {
992         FN_START;
993         if (name == NULL)
994                 return TELECOM_NONE;
995
996         if (g_strcmp0(name, "\"ME\"") == 0)
997                 return TELECOM_PB;
998
999         if (g_strcmp0(name, "\"RC\"") == 0)
1000                 return TELECOM_ICH;
1001
1002         if (g_strcmp0(name, "\"DC\"") == 0)
1003                 return TELECOM_OCH;
1004
1005         if (g_strcmp0(name, "\"MC\"") == 0)
1006                 return TELECOM_MCH;
1007 #ifdef TIZEN_FEATURE_BT_PBAP_SIM
1008         if (g_strcmp0(name, "\"SM\"") == 0)
1009                 return SIM_PB;
1010 #endif
1011         FN_END;
1012         return TELECOM_NONE;
1013 }
1014
1015 static gint __bluetooth_pb_phone_log_filter_append(contacts_filter_h filter,
1016                                                 gint *match, gint size)
1017 {
1018         FN_START;
1019         gint i;
1020         gint status;
1021
1022         for (i = 0; i < size; i++) {
1023
1024                 if (i > 0) {
1025                         status = contacts_filter_add_operator(filter,
1026                                         CONTACTS_FILTER_OPERATOR_OR);
1027
1028                         if (status != CONTACTS_ERROR_NONE)
1029                                 return status;
1030                 }
1031
1032                 status = contacts_filter_add_int(filter,
1033                                         _contacts_phone_log.log_type,
1034                                         CONTACTS_MATCH_EQUAL, match[i]);
1035
1036                 if (status != CONTACTS_ERROR_NONE)
1037                         return status;
1038         }
1039
1040         FN_END;
1041         return CONTACTS_ERROR_NONE;
1042 }
1043
1044 static contacts_query_h __bluetooth_pb_query_phone_log(gint *match, gint size)
1045 {
1046         FN_START;
1047         contacts_query_h query = NULL;
1048         contacts_filter_h filter = NULL;
1049         gint status;
1050
1051         status = contacts_query_create(_contacts_phone_log._uri, &query);
1052
1053         if (status != CONTACTS_ERROR_NONE)
1054                 return NULL;
1055
1056         status = contacts_filter_create(_contacts_phone_log._uri, &filter);
1057
1058         if (status != CONTACTS_ERROR_NONE) {
1059                 contacts_query_destroy(query);
1060                 return NULL;
1061         }
1062
1063         status = __bluetooth_pb_phone_log_filter_append(filter, match, size);
1064
1065         if (status != CONTACTS_ERROR_NONE) {
1066                 contacts_filter_destroy(filter);
1067                 contacts_query_destroy(query);
1068                 return NULL;
1069         }
1070
1071         status = contacts_query_set_filter(query, filter);
1072
1073         if (status != CONTACTS_ERROR_NONE) {
1074                 contacts_filter_destroy(filter);
1075                 contacts_query_destroy(query);
1076                 return NULL;
1077         }
1078
1079         status = contacts_query_set_sort(query, _contacts_phone_log.log_time,
1080                                                                         false);
1081
1082         if (status != CONTACTS_ERROR_NONE) {
1083                 contacts_filter_destroy(filter);
1084                 contacts_query_destroy(query);
1085                 return NULL;
1086         }
1087
1088         contacts_filter_destroy(filter);
1089
1090         FN_END;
1091         return query;
1092 }
1093
1094 bool __bt_is_matching_addressbook(const char *addressbook_name, int addressbook)
1095 {
1096         bool is_sim_addressbook = _bt_is_sim_addressbook(addressbook_name);
1097
1098         if ((is_sim_addressbook == false
1099                         && addressbook == PBAP_ADDRESSBOOK_PHONE) ||
1100                 (is_sim_addressbook == true
1101                         && addressbook == PBAP_ADDRESSBOOK_SIM))
1102                 return true;
1103
1104         return false;
1105 }
1106
1107 static contacts_query_h __bluetooth_pb_query_person(int addressbook)
1108 {
1109         FN_START;
1110         contacts_query_h query = NULL;
1111         contacts_filter_h filter = NULL;
1112         contacts_list_h recordList = NULL;
1113         contacts_record_h record = NULL;
1114         char *addressbook_name = NULL;
1115         int address_book_id = 0;
1116         int count = 0;
1117         unsigned int i = 0;
1118         gint status;
1119         bool is_first_condition = true;
1120
1121         DBG("Addressbook [%d]", addressbook);
1122         /* Create query*/
1123         status = contacts_query_create(_contacts_person_contact._uri, &query);
1124         if (status != 0) {
1125                 ERR("Could not create query");
1126                 return NULL;
1127         }
1128
1129         /* Create addressbook Filter*/
1130         status = contacts_db_get_all_records(_contacts_address_book._uri, 0, 0,
1131                                         &recordList);
1132         if (status != CONTACTS_ERROR_NONE)
1133                 ERR("Contact list get api failed %d", status);
1134
1135         contacts_filter_create(_contacts_person_contact._uri, &filter);
1136         contacts_list_get_count(recordList, &count);
1137
1138         for (i = 0; i < count; i++) {
1139                 status = contacts_list_get_current_record_p(recordList, &record);
1140                 if (status != CONTACTS_ERROR_NONE) {
1141                         ERR("Contact list get api failed %d", status);
1142                         goto next;
1143                 }
1144                 status = contacts_record_get_str_p(record,
1145                                                 _contacts_address_book.name,
1146                                                 &addressbook_name);
1147                 if (status != CONTACTS_ERROR_NONE) {
1148                         ERR("Contact record get api failed %d", status);
1149                         goto next;
1150                 }
1151                 status = contacts_record_get_int(record,
1152                                                 _contacts_address_book.id,
1153                                                 &address_book_id);
1154                 if (status != CONTACTS_ERROR_NONE) {
1155                         ERR("contacts record get int api failed %d", status);
1156                         goto next;
1157                 }
1158
1159                 DBG("Addressbook ID: [%d] Addressbook Name: [%s]",
1160                                 address_book_id, addressbook_name);
1161
1162                 if (__bt_is_matching_addressbook(addressbook_name,
1163                                                         addressbook)) {
1164                         if (is_first_condition)
1165                                 is_first_condition = false;
1166                         else
1167                                 contacts_filter_add_operator(filter,
1168                                                 CONTACTS_FILTER_OPERATOR_OR);
1169                         DBG("SELECTED Addressbook ID: [%d] Addressbook Name: [%s]",
1170                                         address_book_id, addressbook_name);
1171                         status = contacts_filter_add_int(filter,
1172                                         _contacts_person_contact.address_book_id,
1173                                         CONTACTS_MATCH_EQUAL, address_book_id);
1174                         if (status != CONTACTS_ERROR_NONE)
1175                                 ERR("Contact filter add failed %d", status);
1176                 }
1177 next:
1178                 if (contacts_list_next(recordList) != CONTACTS_ERROR_NONE)
1179                         break;
1180         }
1181
1182         contacts_list_destroy(recordList, true);
1183
1184         if (is_first_condition) {
1185                 ERR("ADDRESSBOOK NOT FOUND");
1186                 contacts_filter_destroy(filter);
1187                 contacts_query_destroy(query);
1188                 return NULL;
1189         }
1190
1191         status = contacts_query_set_filter(query, filter);
1192         if (status != CONTACTS_ERROR_NONE)
1193                 ERR("Could not Apply Filter");
1194
1195         contacts_filter_destroy(filter);
1196         FN_END;
1197         return query;
1198 }
1199
1200 static contacts_query_h __bluetooth_pb_query_person_number(void)
1201 {
1202         FN_START;
1203         contacts_query_h query = NULL;
1204         gint status;
1205
1206         status = contacts_query_create(_contacts_person_number._uri, &query);
1207
1208         if (status != CONTACTS_ERROR_NONE)
1209                 return NULL;
1210
1211         FN_END;
1212         return query;
1213 }
1214
1215 static contacts_query_h __bluetooth_pb_query_phone_log_incoming(void)
1216 {
1217         FN_START;
1218         gint size = 4;
1219         gint match[] = {
1220                 CONTACTS_PLOG_TYPE_VOICE_INCOMING,
1221                 CONTACTS_PLOG_TYPE_VIDEO_INCOMING,
1222                 CONTACTS_PLOG_TYPE_VOICE_REJECT,
1223                 CONTACTS_PLOG_TYPE_VIDEO_REJECT
1224         };
1225
1226         FN_END;
1227         return __bluetooth_pb_query_phone_log(match, size);
1228 }
1229
1230 static contacts_query_h __bluetooth_pb_query_phone_log_outgoing(void)
1231 {
1232         FN_START;
1233         gint size = 2;
1234         gint match[] = {
1235                 CONTACTS_PLOG_TYPE_VOICE_OUTGOING,
1236                 CONTACTS_PLOG_TYPE_VIDEO_OUTGOING
1237         };
1238
1239         FN_END;
1240         return __bluetooth_pb_query_phone_log(match, size);
1241 }
1242
1243 static contacts_query_h __bluetooth_pb_query_phone_log_missed(void)
1244 {
1245         FN_START;
1246         gint size = 4;
1247         gint match[] = {
1248                 CONTACTS_PLOG_TYPE_VOICE_INCOMING_UNSEEN,
1249                 CONTACTS_PLOG_TYPE_VIDEO_INCOMING_UNSEEN,
1250                 CONTACTS_PLOG_TYPE_VOICE_INCOMING_SEEN,
1251                 CONTACTS_PLOG_TYPE_VIDEO_INCOMING_SEEN
1252         };
1253
1254         FN_END;
1255         return __bluetooth_pb_query_phone_log(match, size);
1256 }
1257
1258 static contacts_query_h __bluetooth_pb_query_phone_log_combined(void)
1259 {
1260         FN_START;
1261         gint size = 10;
1262         gint match[] = {
1263                 CONTACTS_PLOG_TYPE_VOICE_INCOMING,
1264                 CONTACTS_PLOG_TYPE_VIDEO_INCOMING,
1265                 CONTACTS_PLOG_TYPE_VOICE_OUTGOING,
1266                 CONTACTS_PLOG_TYPE_VIDEO_OUTGOING,
1267                 CONTACTS_PLOG_TYPE_VOICE_INCOMING_UNSEEN,
1268                 CONTACTS_PLOG_TYPE_VIDEO_INCOMING_UNSEEN,
1269                 CONTACTS_PLOG_TYPE_VOICE_INCOMING_SEEN,
1270                 CONTACTS_PLOG_TYPE_VIDEO_INCOMING_SEEN,
1271                 CONTACTS_PLOG_TYPE_VOICE_REJECT,
1272                 CONTACTS_PLOG_TYPE_VIDEO_REJECT
1273         };
1274
1275         FN_END;
1276         return __bluetooth_pb_query_phone_log(match, size);
1277 }
1278
1279 static gboolean __bluetooth_pb_get_count(PhoneBookType pb_type,
1280                                 guint *count)
1281 {
1282         FN_START;
1283         contacts_query_h query = NULL;
1284         gint status;
1285         gint signed_count;
1286
1287         switch (pb_type) {
1288         case TELECOM_PB:
1289                 query = __bluetooth_pb_query_person(PBAP_ADDRESSBOOK_PHONE);
1290                 break;
1291         case TELECOM_ICH:
1292                 query = __bluetooth_pb_query_phone_log_incoming();
1293                 break;
1294         case TELECOM_OCH:
1295                 query = __bluetooth_pb_query_phone_log_outgoing();
1296                 break;
1297         case TELECOM_MCH:
1298                 query = __bluetooth_pb_query_phone_log_missed();
1299                 break;
1300         case TELECOM_CCH:
1301                 query = __bluetooth_pb_query_phone_log_combined();
1302                 break;
1303 #ifdef TIZEN_FEATURE_BT_PBAP_SIM
1304         case SIM_PB:
1305                 query = __bluetooth_pb_query_person(PBAP_ADDRESSBOOK_SIM);
1306                 break;
1307 #endif
1308         default:
1309                 return FALSE;
1310         }
1311
1312         if (query == NULL)
1313                 return FALSE;
1314
1315         status = contacts_db_get_count_with_query(query, &signed_count);
1316
1317         if (status != CONTACTS_ERROR_NONE) {
1318                 contacts_query_destroy(query);
1319                 return FALSE;
1320         }
1321
1322         contacts_query_destroy(query);
1323
1324         if (signed_count < 0)
1325                 signed_count = 0;
1326
1327         *count = (gint) signed_count;
1328
1329         FN_END;
1330         return TRUE;
1331 }
1332
1333 static gboolean __bluetooth_pb_get_count_new_missed_call(guint *count)
1334 {
1335         FN_START;
1336         contacts_query_h query = NULL;
1337         gint status;
1338         gint signed_count;
1339         gint size = 2;
1340         gint match[] = {
1341                 CONTACTS_PLOG_TYPE_VOICE_INCOMING_UNSEEN,
1342                 CONTACTS_PLOG_TYPE_VIDEO_INCOMING_UNSEEN
1343         };
1344
1345         query = __bluetooth_pb_query_phone_log(match, size);
1346
1347         if (query == NULL)
1348                 return FALSE;
1349
1350         status = contacts_db_get_count_with_query(query, &signed_count);
1351
1352         if (status != CONTACTS_ERROR_NONE) {
1353                 contacts_query_destroy(query);
1354                 return FALSE;
1355         }
1356
1357         contacts_query_destroy(query);
1358
1359         if (signed_count < 0)
1360                 signed_count = 0;
1361
1362         *count = (guint)signed_count;
1363
1364         FN_END;
1365         return TRUE;
1366 }
1367
1368 static const char *__bluetooth_pb_phone_log_get_log_type(contacts_record_h record)
1369 {
1370         FN_START;
1371         gint status;
1372         gint log_type;
1373
1374         status = contacts_record_get_int(record, _contacts_phone_log.log_type,
1375                                                                 &log_type);
1376
1377         if (status != CONTACTS_ERROR_NONE)
1378                 return NULL;
1379
1380         switch (log_type) {
1381         case CONTACTS_PLOG_TYPE_VOICE_INCOMING:
1382         case CONTACTS_PLOG_TYPE_VIDEO_INCOMING:
1383         case CONTACTS_PLOG_TYPE_VOICE_REJECT:
1384         case CONTACTS_PLOG_TYPE_VIDEO_REJECT:
1385                 return "RECEIVED";
1386         case CONTACTS_PLOG_TYPE_VOICE_OUTGOING:
1387         case CONTACTS_PLOG_TYPE_VIDEO_OUTGOING:
1388                 return "DIALED";
1389         case CONTACTS_PLOG_TYPE_VOICE_INCOMING_UNSEEN:
1390         case CONTACTS_PLOG_TYPE_VIDEO_INCOMING_UNSEEN:
1391         case CONTACTS_PLOG_TYPE_VOICE_INCOMING_SEEN:
1392         case CONTACTS_PLOG_TYPE_VIDEO_INCOMING_SEEN:
1393                 return "MISSED";
1394         default:
1395                 return NULL;
1396         }
1397         FN_END;
1398 }
1399
1400 static void __bluetooth_pb_get_vcards(PbAgentData *agent, PhoneBookType pb_type,
1401                         guint64 filter, guint8 format, guint16 max_list_count,
1402                         guint16 list_start_offset, GVariantBuilder *vcards)
1403 {
1404         FN_START;
1405         contacts_list_h record_list = NULL;
1406         contacts_query_h query = NULL;
1407         gint status;
1408         gint limit;
1409         gint offset;
1410         guint property_id = 0;
1411         const char *attr = NULL;
1412         gboolean get_log = FALSE;
1413
1414         /* contact offset is n - 1 of PBAP */
1415         offset = (gint)list_start_offset - 1;
1416
1417         if (max_list_count >= 65535)
1418                 limit = -1;     /* contact limit -1 means unrestricted */
1419         else
1420                 limit = (gint)max_list_count;
1421
1422         switch (pb_type) {
1423         case TELECOM_PB:
1424 #ifdef TIZEN_FEATURE_BT_PBAP_SIM
1425         case SIM_PB:
1426 #endif
1427                 /* for owner */
1428                 if (list_start_offset == 0) {
1429                         char *vcard;
1430
1431                         vcard = _bluetooth_pb_vcard_contact_owner(agent->tel_number,
1432                                                                 filter, format);
1433                         if (vcard)
1434                                 g_variant_builder_add(vcards, "s", vcard);
1435
1436                         offset = 0;
1437
1438                         if (limit == 1)
1439                                 return;
1440                         else if (limit > 1)
1441                                 limit--;
1442                 }
1443
1444                 if (pb_type == TELECOM_PB)
1445                         query = __bluetooth_pb_query_person(PBAP_ADDRESSBOOK_PHONE);
1446 #ifdef TIZEN_FEATURE_BT_PBAP_SIM
1447                 else if (pb_type == SIM_PB)
1448                         query = __bluetooth_pb_query_person(PBAP_ADDRESSBOOK_SIM);
1449 #endif
1450
1451                 property_id = _contacts_person.id;
1452                 break;
1453         case TELECOM_ICH:
1454                 query = __bluetooth_pb_query_phone_log_incoming();
1455                 property_id = _contacts_phone_log.id;
1456                 attr = "RECEIVED";
1457                 break;
1458         case TELECOM_OCH:
1459                 query = __bluetooth_pb_query_phone_log_outgoing();
1460                 property_id = _contacts_phone_log.id;
1461                 attr = "DIALED";
1462                 break;
1463         case TELECOM_MCH:
1464                 query = __bluetooth_pb_query_phone_log_missed();
1465                 property_id = _contacts_phone_log.id;
1466                 attr = "MISSED";
1467                 break;
1468         case TELECOM_CCH:
1469                 query = __bluetooth_pb_query_phone_log_combined();
1470                 property_id = _contacts_phone_log.id;
1471                 get_log = TRUE;
1472                 break;
1473         default:
1474                 return;
1475         }
1476         INFO("Limit is = %d and offset is =%d\n", limit, offset);
1477
1478         if (query == NULL) {
1479                 ERR("Query is NULL");
1480                 return;
1481         }
1482         /* When limit is passed as ZERO to contacts_db_get_records_with_query
1483          * API then this API will provide all available contacts in its database
1484          * (unrestricted). Now consider a case when client requests for
1485          * maxlistcount of 1 and start offset as 0 then we have already read the
1486          * owner card in above switch case and when it reads owner card it
1487          * decrements the limit by 1.
1488          */
1489         if (limit != 0) {
1490                 status = contacts_db_get_records_with_query(query, offset,
1491                                                         limit, &record_list);
1492
1493                 if (status != CONTACTS_ERROR_NONE) {
1494                         contacts_list_destroy(record_list, TRUE);
1495                         contacts_query_destroy(query);
1496                         return;
1497                 }
1498
1499                 status = contacts_list_first(record_list);
1500
1501                 if (status != CONTACTS_ERROR_NONE) {
1502                         contacts_list_destroy(record_list, TRUE);
1503                         contacts_query_destroy(query);
1504                         return;
1505                 }
1506
1507                 do {
1508                         contacts_record_h record;
1509                         gint id;
1510                         gchar *vcard = NULL;
1511
1512                         status = contacts_list_get_current_record_p(record_list,
1513                                                                 &record);
1514
1515                         if (status != CONTACTS_ERROR_NONE)
1516                                 continue;
1517                         status = contacts_record_get_int(record, property_id,
1518                                                                         &id);
1519
1520                         if (status != CONTACTS_ERROR_NONE)
1521                                 continue;
1522
1523                         if (property_id == _contacts_person.id)
1524                                 vcard = _bluetooth_pb_vcard_contact(id, filter,
1525                                                                         format);
1526                         else {
1527                                 if (get_log)
1528                                         attr = __bluetooth_pb_phone_log_get_log_type(record);
1529
1530                                 vcard = _bluetooth_pb_vcard_call(id, filter,
1531                                                                 format, attr);
1532                         }
1533
1534                         if (vcard)
1535                                 g_variant_builder_add(vcards, "s", vcard);
1536
1537                 } while (contacts_list_next(record_list) == CONTACTS_ERROR_NONE);
1538                 contacts_list_destroy(record_list, TRUE);
1539         }
1540
1541         contacts_query_destroy(query);
1542
1543         FN_END;
1544 }
1545
1546 static void __bluetooth_pb_get_contact_list(PbAgentData *agent,
1547                         contacts_query_h query, GVariantBuilder *builder)
1548 {
1549         FN_START;
1550         contacts_list_h record_list = NULL;
1551         gint status;
1552
1553         /* Add owner */
1554         if (builder) {
1555                 gchar *tmp;
1556                 gchar *name;
1557
1558                 tmp = _bluetooth_pb_owner_name();
1559                 name = g_strdup_printf("%s;;;;", tmp);
1560                 g_free(tmp);
1561
1562                 __bluetooth_pb_list_ptr_array_add(builder, name,
1563                                                         agent->tel_number, 0);
1564
1565                 g_free(name);
1566         }
1567
1568         if (query == NULL) {
1569                 ERR("Query is NULL");
1570                 return;
1571         }
1572
1573         status = contacts_db_get_records_with_query(query, -1, -1,
1574                                                                 &record_list);
1575
1576         if (status != CONTACTS_ERROR_NONE) {
1577                 contacts_list_destroy(record_list, TRUE);
1578                 return;
1579         }
1580
1581         status = contacts_list_first(record_list);
1582
1583         if (status != CONTACTS_ERROR_NONE) {
1584                 contacts_list_destroy(record_list, TRUE);
1585                 return;
1586         }
1587
1588         do {
1589                 contacts_record_h record;
1590                 gint id;
1591
1592                 status = contacts_list_get_current_record_p(record_list,
1593                                                                 &record);
1594
1595                 if (status != CONTACTS_ERROR_NONE)
1596                         continue;
1597
1598                 status = contacts_record_get_int(record,
1599                                 _contacts_person_contact.person_id, &id);
1600
1601                 if (status != CONTACTS_ERROR_NONE)
1602                         continue;
1603
1604                 /* create list */
1605                 if (builder) {
1606                         gchar *name;
1607                         gchar *number;
1608
1609                         name = _bluetooth_pb_name_from_person_id(id);
1610                         number = _bluetooth_pb_number_from_person_id(id);
1611
1612                         __bluetooth_pb_list_ptr_array_add(builder, name,
1613                                                                 number, id);
1614
1615                         g_free(name);
1616                         g_free(number);
1617                 }
1618
1619         } while (contacts_list_next(record_list) == CONTACTS_ERROR_NONE);
1620
1621         contacts_list_destroy(record_list, TRUE);
1622         FN_END;
1623 }
1624
1625 static void __bluetooth_pb_get_phone_log_list(PbAgentData *agent,
1626                         contacts_query_h query, GVariantBuilder *builder)
1627 {
1628         FN_START;
1629         contacts_list_h record_list = NULL;
1630         gint status;
1631
1632         status = contacts_db_get_records_with_query(query, -1, -1,
1633                                                                 &record_list);
1634
1635         if (status != CONTACTS_ERROR_NONE)
1636                 return;
1637
1638         status = contacts_list_first(record_list);
1639
1640         if (status != CONTACTS_ERROR_NONE) {
1641                 contacts_list_destroy(record_list, TRUE);
1642                 return;
1643         }
1644
1645         do {
1646                 contacts_record_h record;
1647                 gint id;
1648
1649                 status = contacts_list_get_current_record_p(record_list,
1650                                                                 &record);
1651
1652                 if (status != CONTACTS_ERROR_NONE)
1653                         continue;
1654
1655                 status = contacts_record_get_int(record,
1656                                                 _contacts_phone_log.id, &id);
1657
1658                 if (status != CONTACTS_ERROR_NONE)
1659                         continue;
1660
1661                 /* create list */
1662                 if (builder) {
1663                         gchar *name;
1664                         gchar *number;
1665
1666                         name = _bluetooth_pb_name_from_phonelog_id(id);
1667
1668                         contacts_record_get_str_p(record,
1669                                         _contacts_phone_log.address, &number);
1670
1671                         __bluetooth_pb_list_ptr_array_add(builder, name,
1672                                                                 number, id);
1673
1674                         g_free(name);
1675                 }
1676
1677         } while (contacts_list_next(record_list) == CONTACTS_ERROR_NONE);
1678
1679         contacts_list_destroy(record_list, TRUE);
1680         FN_END;
1681 }
1682
1683
1684 static void __bluetooth_pb_get_list(PbAgentData *agent, PhoneBookType pb_type,
1685                                 GVariantBuilder *builder)
1686 {
1687         FN_START;
1688         contacts_query_h query;
1689
1690         /* no requires refresh cache */
1691         if (builder == NULL && agent->pb_type == pb_type)
1692                 return;
1693
1694         switch (pb_type) {
1695         case TELECOM_PB:
1696                 query = __bluetooth_pb_query_person(PBAP_ADDRESSBOOK_PHONE);
1697                 __bluetooth_pb_get_contact_list(agent, query, builder);
1698                 break;
1699         case TELECOM_ICH:
1700                 query = __bluetooth_pb_query_phone_log_incoming();
1701                 __bluetooth_pb_get_phone_log_list(agent, query, builder);
1702                 break;
1703         case TELECOM_OCH:
1704                 query = __bluetooth_pb_query_phone_log_outgoing();
1705                 __bluetooth_pb_get_phone_log_list(agent, query, builder);
1706                 break;
1707         case TELECOM_MCH:
1708                 query = __bluetooth_pb_query_phone_log_missed();
1709                 __bluetooth_pb_get_phone_log_list(agent, query, builder);
1710                 break;
1711         case TELECOM_CCH:
1712                 query = __bluetooth_pb_query_phone_log_combined();
1713                 __bluetooth_pb_get_phone_log_list(agent, query, builder);
1714                 break;
1715 #ifdef TIZEN_FEATURE_BT_PBAP_SIM
1716         case SIM_PB:
1717                 query = __bluetooth_pb_query_person(PBAP_ADDRESSBOOK_SIM);
1718                 __bluetooth_pb_get_contact_list(agent, query, builder);
1719                 break;
1720 #endif
1721         default:
1722                 return;
1723         }
1724
1725         agent->pb_type = pb_type;
1726
1727         if (query)
1728                 contacts_query_destroy(query);
1729         FN_END;
1730 }
1731
1732 static void __bluetooth_pb_get_contact_list_number(PbAgentData *agent,
1733                                 contacts_query_h query, gint start_index,
1734                                 gint end_index, GVariantBuilder *builder)
1735 {
1736         FN_START;
1737         contacts_list_h record_list = NULL;
1738         gint status;
1739         gint i;
1740         gint from;
1741         gint to;
1742         gint offset;
1743
1744         from = start_index;
1745         to = end_index;
1746
1747         if (from < 1)
1748                 from = 1;
1749
1750         if (to < 1)
1751                 to = 1;
1752
1753         offset = to - from + 1;
1754         if (offset <= 0)
1755                 return;
1756
1757         i = from;
1758
1759         status = contacts_db_get_records_with_query(query, from - 1 , offset,
1760                         &record_list);
1761
1762         if (status != CONTACTS_ERROR_NONE) {
1763                 contacts_list_destroy(record_list, TRUE);
1764                 return;
1765         }
1766
1767         status = contacts_list_first(record_list);
1768
1769         if (status != CONTACTS_ERROR_NONE) {
1770                 contacts_list_destroy(record_list, TRUE);
1771                 return;
1772         }
1773
1774         do {
1775                 contacts_record_h record;
1776                 gchar *display_name;
1777                 gchar *number;
1778
1779                 status = contacts_list_get_current_record_p(record_list,
1780                                                                 &record);
1781
1782                 if (status != CONTACTS_ERROR_NONE)
1783                         continue;
1784
1785                 contacts_record_get_str_p(record,
1786                                         _contacts_person_number.display_name,
1787                                         &display_name);
1788                 contacts_record_get_str_p(record,
1789                                 _contacts_person_number.number, &number);
1790
1791                 __bluetooth_pb_list_ptr_array_add(builder, display_name,
1792                                                                 number, i);
1793
1794                 i++;
1795         } while (contacts_list_next(record_list) == CONTACTS_ERROR_NONE);
1796
1797         contacts_list_destroy(record_list, TRUE);
1798         FN_END;
1799 }
1800
1801 static void __bluetooth_pb_get_phone_log_list_number(PbAgentData *agent,
1802                                 contacts_query_h query, gint start_index,
1803                                 gint end_index, GVariantBuilder *builder)
1804 {
1805         FN_START;
1806         contacts_list_h record_list = NULL;
1807         gint status;
1808         gint i;
1809         gint from;
1810         gint to;
1811         gint offset;
1812
1813         from = start_index;
1814         to = end_index;
1815
1816         if (from < 1)
1817                 from = 1;
1818
1819         if (to < 1)
1820                 to = 1;
1821
1822         offset = to - from + 1;
1823         if (offset <= 0)
1824                 return;
1825
1826         i = from;
1827
1828         status = contacts_db_get_records_with_query(query, from - 1 , offset,
1829                         &record_list);
1830
1831         if (status != CONTACTS_ERROR_NONE) {
1832                 contacts_list_destroy(record_list, TRUE);
1833                 return;
1834         }
1835
1836         status = contacts_list_first(record_list);
1837         if (status != CONTACTS_ERROR_NONE) {
1838                 contacts_list_destroy(record_list, TRUE);
1839                 return;
1840         }
1841
1842         do {
1843                 contacts_record_h record;
1844                 gint id;
1845                 gchar *display_name;
1846                 gchar *number;
1847
1848                 status = contacts_list_get_current_record_p(record_list,
1849                                                                 &record);
1850
1851                 if (status != CONTACTS_ERROR_NONE)
1852                         continue;
1853
1854                 status = contacts_record_get_int(record,
1855                                                 _contacts_phone_log.id, &id);
1856                 if (status != CONTACTS_ERROR_NONE) {
1857                         ERR("contact_record_get_int api failed %d", status);
1858                         continue;
1859                 }
1860
1861                 display_name = _bluetooth_pb_fn_from_phonelog_id(id);
1862
1863                 contacts_record_get_str_p(record, _contacts_phone_log.address,
1864                                                                 &number);
1865
1866                 __bluetooth_pb_list_ptr_array_add(builder, display_name,
1867                                                                 number, i);
1868
1869                 i++;
1870
1871                 g_free(display_name);
1872
1873         } while (contacts_list_next(record_list) == CONTACTS_ERROR_NONE);
1874
1875         contacts_list_destroy(record_list, TRUE);
1876         FN_END;
1877 }
1878
1879 static void __bluetooth_pb_get_list_number(PbAgentData *agent,
1880                                 PhoneBookType pb_type, gint start_index,
1881                                 gint end_index, GVariantBuilder *builder)
1882 {
1883         FN_START;
1884         contacts_query_h query;
1885
1886         DBG("type = %d", pb_type);
1887         switch (pb_type) {
1888         case TELECOM_PB:
1889                 query = __bluetooth_pb_query_person(PBAP_ADDRESSBOOK_PHONE);
1890                 __bluetooth_pb_get_contact_list_number(agent, query,
1891                                 start_index, end_index, builder);
1892                 break;
1893         case TELECOM_ICH:
1894                 query = __bluetooth_pb_query_phone_log_incoming();
1895                 __bluetooth_pb_get_phone_log_list_number(agent, query,
1896                                 start_index, end_index, builder);
1897                 break;
1898         case TELECOM_OCH:
1899                 query = __bluetooth_pb_query_phone_log_outgoing();
1900                 __bluetooth_pb_get_phone_log_list_number(agent, query,
1901                                 start_index, end_index, builder);
1902                 break;
1903         case TELECOM_MCH:
1904                 query = __bluetooth_pb_query_phone_log_missed();
1905                 __bluetooth_pb_get_phone_log_list_number(agent, query,
1906                                 start_index, end_index, builder);
1907                 break;
1908         case TELECOM_CCH:
1909                 query = __bluetooth_pb_query_phone_log_combined();
1910                 __bluetooth_pb_get_phone_log_list_number(agent, query,
1911                                 start_index, end_index, builder);
1912                 break;
1913 #ifdef TIZEN_FEATURE_BT_PBAP_SIM
1914         case SIM_PB:
1915                 query = __bluetooth_pb_query_person(PBAP_ADDRESSBOOK_SIM);
1916                 __bluetooth_pb_get_contact_list_number(agent, query,
1917                                 start_index, end_index, builder);
1918                 break;
1919 #endif
1920
1921         default:
1922                 return;
1923         }
1924
1925         if (query)
1926                 contacts_query_destroy(query);
1927         FN_END;
1928 }
1929
1930 static void __bluetooth_pb_get_contact_list_name(PbAgentData *agent,
1931                                 contacts_query_h query, const gchar *find_text,
1932                                 GVariantBuilder *builder)
1933 {
1934         FN_START;
1935         contacts_list_h record_list = NULL;
1936         gint status;
1937         gint i = 1;
1938
1939         status = contacts_db_get_records_with_query(query,
1940                         -1, -1, &record_list);
1941
1942         if (status != CONTACTS_ERROR_NONE) {
1943                 contacts_list_destroy(record_list, TRUE);
1944                 return;
1945         }
1946
1947         status = contacts_list_first(record_list);
1948
1949         if (status != CONTACTS_ERROR_NONE) {
1950                 contacts_list_destroy(record_list, TRUE);
1951                 return;
1952         }
1953
1954         do {
1955                 contacts_record_h record;
1956                 gchar *display_name;
1957
1958                 status = contacts_list_get_current_record_p(record_list,
1959                                                                 &record);
1960
1961                 if (status != CONTACTS_ERROR_NONE)
1962                         continue;
1963
1964                 contacts_record_get_str_p(record,
1965                         _contacts_person_number.display_name, &display_name);
1966
1967                 if (g_str_has_prefix(display_name, find_text)) {
1968                         gchar *number;
1969
1970                         contacts_record_get_str_p(record,
1971                                 _contacts_person_number.number, &number);
1972
1973                         __bluetooth_pb_list_ptr_array_add(builder, display_name,
1974                                                                 number, i);
1975                 }
1976
1977                 i++;
1978         } while (contacts_list_next(record_list) == CONTACTS_ERROR_NONE);
1979         contacts_list_destroy(record_list, TRUE);
1980         FN_END;
1981 }
1982
1983 static void __bluetooth_pb_get_phone_log_list_name(PbAgentData *agent,
1984                                 contacts_query_h query, const gchar *find_text,
1985                                 GVariantBuilder *builder)
1986 {
1987         FN_START;
1988         contacts_list_h record_list = NULL;
1989         gint status;
1990         gint i = 1;
1991
1992         status = contacts_db_get_records_with_query(query, -1, -1,
1993                                                                 &record_list);
1994
1995         if (status != CONTACTS_ERROR_NONE) {
1996                 contacts_list_destroy(record_list, TRUE);
1997                 return;
1998         }
1999
2000         status = contacts_list_first(record_list);
2001
2002         if (status != CONTACTS_ERROR_NONE) {
2003                 contacts_list_destroy(record_list, TRUE);
2004                 return;
2005         }
2006
2007         do {
2008                 contacts_record_h record;
2009                 gint id;
2010                 gchar *display_name;
2011
2012                 status = contacts_list_get_current_record_p(record_list,
2013                                 &record);
2014
2015                 if (status != CONTACTS_ERROR_NONE)
2016                         continue;
2017
2018                 status = contacts_record_get_int(record,
2019                                                 _contacts_phone_log.id, &id);
2020                 if (status != CONTACTS_ERROR_NONE) {
2021                         ERR("contacts_record_get_int failed %d", status);
2022                         continue;
2023                 }
2024
2025                 display_name = _bluetooth_pb_fn_from_phonelog_id(id);
2026
2027                 if (g_str_has_prefix(display_name, find_text)) {
2028                         gchar *number;
2029
2030                         contacts_record_get_str_p(record,
2031                                         _contacts_phone_log.address, &number);
2032
2033                         __bluetooth_pb_list_ptr_array_add(builder, display_name,
2034                                                                 number, i);
2035                 }
2036
2037                 i++;
2038
2039                 g_free(display_name);
2040
2041         } while (contacts_list_next(record_list) == CONTACTS_ERROR_NONE);
2042
2043         contacts_list_destroy(record_list, TRUE);
2044         FN_END;
2045 }
2046
2047 static void __bluetooth_pb_get_list_name(PbAgentData *agent,
2048                                 PhoneBookType pb_type, const gchar *find_text,
2049                                 GVariantBuilder *builder)
2050 {
2051         FN_START;
2052         contacts_query_h query;
2053
2054         switch (pb_type) {
2055         case TELECOM_PB:
2056                 query = __bluetooth_pb_query_person_number();
2057                 __bluetooth_pb_get_contact_list_name(agent, query,
2058                                 find_text, builder);
2059                 break;
2060         case TELECOM_ICH:
2061                 query = __bluetooth_pb_query_phone_log_incoming();
2062                 __bluetooth_pb_get_phone_log_list_name(agent, query,
2063                                 find_text, builder);
2064                 break;
2065         case TELECOM_OCH:
2066                 query = __bluetooth_pb_query_phone_log_outgoing();
2067                 __bluetooth_pb_get_phone_log_list_name(agent, query,
2068                                 find_text, builder);
2069                 break;
2070         case TELECOM_MCH:
2071                 query = __bluetooth_pb_query_phone_log_missed();
2072                 __bluetooth_pb_get_phone_log_list_name(agent, query,
2073                                 find_text, builder);
2074                 break;
2075         case TELECOM_CCH:
2076                 query = __bluetooth_pb_query_phone_log_combined();
2077                 __bluetooth_pb_get_phone_log_list_name(agent, query,
2078                                 find_text, builder);
2079                 break;
2080         default:
2081                 return;
2082         }
2083
2084         if (query)
2085                 contacts_query_destroy(query);
2086         FN_END;
2087 }
2088
2089 static void __bluetooth_pb_list_ptr_array_add(GVariantBuilder *builder,
2090                         const gchar *name, const gchar *number, gint handle)
2091 {
2092         FN_START;
2093         gchar *temp_name = g_strdup(name);
2094         gchar *temp_number = g_strdup(number);
2095
2096         g_variant_builder_add(builder, "(ssu)", temp_name, temp_number, handle);
2097
2098         g_free(temp_name);
2099         g_free(temp_number)
2100         FN_END;
2101 }
2102
2103 static void __bluetooth_pb_agent_signal_handler(int signum)
2104 {
2105         FN_START;
2106         if (g_mainloop) {
2107                 g_main_loop_quit(g_mainloop);
2108         } else {
2109                 DBG("Terminate Bluetooth PBAP agent");
2110                 exit(0);
2111         }
2112 }
2113
2114 static void __bluetooth_pb_contact_changed(const gchar *view_uri,
2115                                         void *user_data)
2116 {
2117         FN_START;
2118         guint new_missed_call;
2119         PbAgentData *agent = (PbAgentData *)user_data;
2120         GDBusConnection *conn = __bt_pb_get_gdbus_connection();
2121
2122         DBG("Received contact changed cb");
2123
2124         g_dbus_connection_emit_signal(conn, NULL,
2125                                 "/org/bluez/pb_agent", "org.bluez.PbAgent",
2126                                 "clear", NULL, NULL);
2127
2128         bluetooth_pb_agent_clear(agent);
2129
2130         __bluetooth_pb_get_count_new_missed_call(&new_missed_call);
2131
2132         if (new_missed_call > total_missed_call_count)
2133                 unnotified_missed_call_count += new_missed_call -
2134                                                         total_missed_call_count;
2135
2136         INFO("Missed call count : #prev[%d], #current[%d], #unnotified[%d]",
2137                 total_missed_call_count, new_missed_call,
2138                                                 unnotified_missed_call_count);
2139
2140         total_missed_call_count = new_missed_call;
2141         FN_END;
2142 }
2143
2144 static void __bluetooth_pb_agent_timeout_add_seconds(PbAgentData *agent)
2145 {
2146         FN_START;
2147
2148         if (agent->timeout_id)
2149                 g_source_remove(agent->timeout_id);
2150
2151         agent->timeout_id = g_timeout_add_seconds(BLUETOOTH_PB_AGENT_TIMEOUT,
2152                                 __bluetooth_pb_agent_timeout_calback, agent);
2153         FN_END;
2154 }
2155
2156 static gboolean __bluetooth_pb_agent_timeout_calback(gpointer user_data)
2157 {
2158         FN_START;
2159         PbAgentData *agent = (PbAgentData *)user_data;
2160
2161         agent->timeout_id = 0;
2162
2163         if (g_mainloop)
2164                 g_main_loop_quit(g_mainloop);
2165
2166         FN_END;
2167         return FALSE;
2168 }
2169
2170 static void __bluetooth_pb_tel_callback(TapiHandle *handle, int result,
2171                                         void *data, void *user_data)
2172 {
2173         FN_START;
2174         PbAgentData *agent = (PbAgentData *)user_data;
2175         TelSimMsisdnList_t *number;
2176
2177         __bt_pb_dbus_init(agent);
2178
2179         if (data != NULL) {
2180                 number = (TelSimMsisdnList_t *)data;
2181                 agent->tel_number = g_strdup(number->list[0].num);
2182         }
2183
2184         tel_deinit(agent->tapi_handle);
2185         agent->tapi_handle = NULL;
2186         FN_END;
2187 }
2188
2189 static gboolean __bt_pb_destroy_agent()
2190 {
2191         FN_START;
2192         g_main_loop_quit(g_mainloop);
2193         FN_END;
2194         return TRUE;
2195 }
2196
2197 static GDBusNodeInfo *__bt_pb_create_method_node_info
2198                                         (const gchar *introspection_data)
2199 {
2200         GError *err = NULL;
2201         GDBusNodeInfo *node_info = NULL;
2202
2203         if (introspection_data == NULL)
2204                 return NULL;
2205
2206         node_info = g_dbus_node_info_new_for_xml(introspection_data, &err);
2207
2208         if (err) {
2209                 ERR("Unable to create node: %s", err->message);
2210                 g_clear_error(&err);
2211         }
2212         return node_info;
2213 }
2214
2215 static gboolean __bt_pb_dbus_init(PbAgentData *agent)
2216 {
2217         guint owner_id = 0;
2218         guint pb_id;
2219         GDBusNodeInfo *node_info = NULL;
2220         GError *error = NULL;
2221         GDBusConnection *conn = __bt_pb_get_gdbus_connection();
2222
2223         if (conn == NULL) {
2224                 ERR("Error in creating the gdbus connection");
2225                 goto fail;
2226         }
2227
2228         owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM, BT_PB_SERVICE_NAME,
2229                                         G_BUS_NAME_OWNER_FLAGS_NONE, NULL,
2230                                         NULL, NULL, NULL, NULL);
2231         if (owner_id == 0)
2232                 goto fail;
2233
2234         node_info = __bt_pb_create_method_node_info(pb_agent_introspection_xml);
2235         if (node_info == NULL)
2236                 goto fail;
2237
2238         pb_id = g_dbus_connection_register_object(conn, BT_PB_SERVICE_OBJECT_PATH,
2239                                         node_info->interfaces[0], &method_table,
2240                                         agent, NULL, &error);
2241
2242         if (pb_id == 0) {
2243                 ERR("Failed to register: %s", error->message);
2244                 g_clear_error(&error);
2245                 goto fail;
2246         }
2247
2248         agent->pbagent_interface_id = pb_id;
2249
2250         pb_id = g_dbus_connection_register_object(conn, BT_PB_SERVICE_OBJECT_PATH,
2251                                         node_info->interfaces[1], &method_table,
2252                                         agent, NULL, &error);
2253
2254         if (pb_id == 0) {
2255                 ERR("Failed to register: %s", error->message);
2256                 g_clear_error(&error);
2257                 goto fail;
2258         }
2259
2260         g_dbus_node_info_unref(node_info);
2261
2262         agent->pbagent_at_interface_id = pb_id;
2263
2264         return TRUE;
2265
2266 fail:
2267         if (pb_dbus_conn) {
2268                 g_object_unref(pb_dbus_conn);
2269                 pb_dbus_conn = NULL;
2270         }
2271
2272         if (conn)
2273                 g_object_unref(conn);
2274
2275         if (node_info)
2276                 g_dbus_node_info_unref(node_info);
2277
2278         if (owner_id > 0)
2279                 g_bus_unown_name(owner_id);
2280
2281         return FALSE;
2282 }
2283
2284 static gboolean __bt_pb_dbus_deinit(PbAgentData *agent)
2285 {
2286         if (pb_dbus_conn) {
2287                 if (agent->pbagent_interface_id != 0) {
2288                         g_dbus_connection_unregister_object(pb_dbus_conn,
2289                                                 agent->pbagent_interface_id);
2290                         agent->pbagent_interface_id = 0;
2291                 }
2292                 if (agent->pbagent_at_interface_id != 0) {
2293                         g_dbus_connection_unregister_object(pb_dbus_conn,
2294                                                 agent->pbagent_at_interface_id);
2295                         agent->pbagent_at_interface_id = 0;
2296                 }
2297                 if (pb_dbus_conn) {
2298                         g_object_unref(pb_dbus_conn);
2299                         pb_dbus_conn = NULL;
2300                 }
2301                 return TRUE;
2302         }
2303         return FALSE;
2304 }
2305
2306 int main(void)
2307 {
2308         FN_START;
2309         PbAgentData *agent;
2310         gint ret = EXIT_SUCCESS;
2311         gint tapi_result;
2312         struct sigaction sa;
2313
2314         DBG("Starting Bluetooth PBAP agent");
2315
2316         g_mainloop = g_main_loop_new(NULL, FALSE);
2317         if (g_mainloop == NULL) {
2318                 ERR("Couldn't create GMainLoop\n");
2319                 return EXIT_FAILURE;
2320         }
2321
2322         agent = (PbAgentData *)g_malloc(sizeof(PbAgentData));
2323
2324         if (agent == NULL)
2325                 return EXIT_FAILURE;
2326
2327         agent->pbagent_interface_id = 0;
2328         agent->pbagent_at_interface_id = 0;
2329         agent->tel_number = NULL;
2330
2331         /* connect contact */
2332         if (contacts_connect() != CONTACTS_ERROR_NONE) {
2333                 ERR("Can not connect contacts server\n");
2334                 g_free(agent);
2335                 return EXIT_FAILURE;
2336         }
2337
2338         __bluetooth_pb_get_count_new_missed_call(&total_missed_call_count);
2339
2340         if (contacts_db_add_changed_cb(_contacts_contact._uri,
2341                         __bluetooth_pb_contact_changed,
2342                         (void *)agent) != CONTACTS_ERROR_NONE) {
2343                 ERR("Can not add changed callback");
2344         }
2345
2346         if (contacts_db_add_changed_cb(_contacts_phone_log._uri,
2347                         __bluetooth_pb_contact_changed,
2348                         (void *)agent) != CONTACTS_ERROR_NONE) {
2349                 ERR("Can not add changed callback");
2350         }
2351
2352         /* set signal */
2353         memset(&sa, 0, sizeof(sa));
2354         sa.sa_handler = __bluetooth_pb_agent_signal_handler;
2355         sigaction(SIGTERM, &sa, NULL);
2356         sigaction(SIGINT, &sa, NULL);
2357
2358         /* init tapi */
2359         agent->tapi_handle = tel_init(NULL);
2360         tapi_result = tel_get_sim_msisdn(agent->tapi_handle,
2361                         __bluetooth_pb_tel_callback, agent);
2362
2363         if (tapi_result != TAPI_API_SUCCESS)
2364                 __bt_pb_dbus_init(agent);
2365
2366         __bluetooth_pb_agent_timeout_add_seconds(agent);
2367
2368         g_main_loop_run(g_mainloop);
2369
2370         if (contacts_db_remove_changed_cb(_contacts_phone_log._uri,
2371                         __bluetooth_pb_contact_changed,
2372                         (void *)agent) != CONTACTS_ERROR_NONE) {
2373                 ERR("Cannot remove changed callback");
2374         }
2375
2376         if (contacts_db_remove_changed_cb(_contacts_contact._uri,
2377                         __bluetooth_pb_contact_changed,
2378                         (void *)agent) != CONTACTS_ERROR_NONE) {
2379                 ERR("Cannot remove changed callback");
2380         }
2381
2382         if (contacts_disconnect() != CONTACTS_ERROR_NONE)
2383                 ERR("contacts_disconnect failed \n");
2384
2385         g_dbus_connection_emit_signal(pb_dbus_conn, NULL,
2386                                 "/org/bluez/pb_agent", "org.bluez.PbAgent",
2387                                 "clear", NULL, NULL);
2388
2389         bluetooth_pb_agent_clear(agent);
2390
2391         if (agent->tapi_handle)
2392                 tel_deinit(agent->tapi_handle);
2393         if (agent->tel_number)
2394                 g_free(agent->tel_number);
2395
2396         __bt_pb_dbus_deinit(agent);
2397
2398         g_free(agent);
2399
2400         DBG("Terminate Bluetooth PBAP agent");
2401         FN_END;
2402         return ret;
2403 }