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