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