Dynamic interval table for multi handle
[platform/core/location/lbs-dbus.git] / server / src / lbs_dbus_server.c
1 /*
2  * lbs-dbus
3  *
4  * Copyright (c) 2013 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Youngae Kang <youngae.kang@samsung.com>, Minjune Kim <sena06.kim@samsung.com>
7  *                      Genie Kim <daejins.kim@samsung.com>, Ming Zhu <mingwu.zhu@samsung.com>
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  * http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  */
21
22 #include <stdio.h>
23
24 #include "generated-code.h"
25 #include "lbs_dbus_server.h"
26 #include "lbs_dbus_server_priv.h"
27
28 typedef struct _lbs_server_dbus_s {
29         /* LBS server dbus info */
30         gchar *service_name;
31         gchar *prev_owner;
32         gchar *service_path;
33         gchar *name;
34         gchar *description;
35         GHashTable *connections;
36         gint status;
37         GDBusObjectManagerServer *manager;
38         LbsObjectSkeleton *obj_skeleton;
39
40         LbsDbusSetOptionsCB set_options_cb;
41         LbsDbusShutdownCB shutdown_cb;
42         LbsDbusUpdateIntervalCB update_interval_cb;
43         LbsDbusRequestChangeIntervalCB request_change_interval_cb;
44         LbsDbusGetNmeaCB get_nmea_cb;
45         gpointer userdata;      /* used for save GpsManager */
46
47         guint owner_changed_id;
48         guint owner_id;
49         guint get_providerinfo_h;
50         guint get_status_h;
51         guint set_option_h;
52         guint add_reference_h;
53         guint remove_reference_h;
54         guint get_nmea_h;
55
56         /* for geofence */
57         guint add_fence_h;
58         guint remove_fence_h;
59         guint pause_fence_h;
60         guint resume_fence_h;
61         guint start_geofence_h;
62         guint stop_geofence_h;
63         gint geofence_status;
64
65         /* for H/W gps-geofence */
66         guint add_hw_fence_h;
67         guint delete_hw_fence_h;
68         guint pause_hw_fence_h;
69         guint resume_hw_fence_h;
70         gint hw_geofence_status;
71         GpsGeofenceAddFenceCB add_hw_fence_cb;
72         GpsGeofenceDeleteFenceCB delete_hw_fence_cb;
73         GpsGeofencePauseFenceCB pause_hw_fence_cb;
74         GpsGeofenceResumeFenceCB resume_hw_fence_cb;
75
76         /* Tizen 3.0 */
77         guint set_mock_location_h;
78         LbsDbusSetMockLocationCB set_mock_location_cb;
79
80 #ifdef TIZEN_3_0_OPT
81         lbs_server_dbus_cb_t callback;
82 #endif
83 } lbs_server_dbus_s;
84
85 typedef enum {
86         LBS_SERVER_METHOD_GPS = 0,
87         LBS_SERVER_METHOD_NPS,
88         LBS_SERVER_METHOD_AGPS,
89         LBS_SERVER_METHOD_GEOFENCE,
90         LBS_SERVER_METHOD_MOCK,
91         LBS_SERVER_METHOD_SIZE,
92 } lbs_server_method_e;
93
94 static gboolean lbs_dbus_setup_position_interface(LbsObjectSkeleton *object, lbs_server_dbus_s *ctx)
95 {
96         LBS_SERVER_LOGD("lbs_dbus_setup_position_interface");
97         if (!object || !ctx)
98                 return FALSE;
99
100         LbsPosition *position = NULL;
101         position = lbs_position_skeleton_new();
102         lbs_object_skeleton_set_position(object, position);
103         g_object_unref(position);
104
105         return TRUE;
106 }
107
108 static gboolean lbs_dbus_setup_batch_interface(LbsObjectSkeleton *object, lbs_server_dbus_s *ctx)
109 {
110         LBS_SERVER_LOGD("lbs_dbus_setup_batch_interface");
111         if (!object || !ctx)
112                 return FALSE;
113
114         LbsBatch *batch = NULL;
115         batch = lbs_batch_skeleton_new();
116         lbs_object_skeleton_set_batch(object, batch);
117         g_object_unref(batch);
118
119         return TRUE;
120 }
121
122 static gboolean lbs_dbus_setup_satellite_interface(LbsObjectSkeleton *object, lbs_server_dbus_s *ctx)
123 {
124         LBS_SERVER_LOGD("lbs_dbus_setup_satellite_interface");
125         if (!object || !ctx)
126                 return FALSE;
127
128         LbsSatellite *sat = NULL;
129         sat = lbs_satellite_skeleton_new();
130         lbs_object_skeleton_set_satellite(object, sat);
131         g_object_unref(sat);
132
133         return TRUE;
134 }
135
136 static gboolean lbs_dbus_setup_nmea_interface(LbsObjectSkeleton *object, lbs_server_dbus_s *ctx)
137 {
138         LBS_SERVER_LOGD("lbs_dbus_setup_nmea_interface");
139         if (!object || !ctx)
140                 return FALSE;
141
142         LbsNmea *nmea = NULL;
143         nmea = lbs_nmea_skeleton_new();
144         lbs_object_skeleton_set_nmea(object, nmea);
145         g_object_unref(nmea);
146
147         return TRUE;
148 }
149
150 static gboolean lbs_dbus_setup_gps_geofence_interface(LbsObjectSkeleton *object, lbs_server_dbus_s *ctx)
151 {
152         LBS_SERVER_LOGD("lbs_dbus_setup_gps_geofence_interface");
153         if (!object || !ctx)
154                 return FALSE;
155
156         LbsGpsGeofence *gps_geofence = NULL;
157         gps_geofence = lbs_gps_geofence_skeleton_new();
158         lbs_object_skeleton_set_gps_geofence(object, gps_geofence);
159         g_object_unref(gps_geofence);
160
161         return TRUE;
162 }
163
164
165 static gboolean
166 on_manager_getproviderinfo(LbsManager *mgr, GDBusMethodInvocation *invocation, gpointer user_data)
167 {
168         LBS_SERVER_LOGD("on_manager_getproviderinfo");
169         lbs_server_dbus_s *ctx = (lbs_server_dbus_s *)user_data;
170         if (!ctx)
171                 return FALSE;
172
173         if (ctx->name && ctx->description)
174                 lbs_manager_complete_get_provider_info(mgr, invocation, ctx->name, ctx->description);
175         else
176                 lbs_manager_complete_get_provider_info(mgr, invocation, NULL, NULL);
177
178         return TRUE;
179 }
180
181 static gboolean
182 on_manager_getstatus(LbsManager *mgr, GDBusMethodInvocation *invocation, gpointer user_data)
183 {
184         LBS_SERVER_LOGD("on_manager_getstatus");
185         lbs_server_dbus_s *ctx = (lbs_server_dbus_s *)user_data;
186         if (!ctx)
187                 return FALSE;
188
189         lbs_manager_complete_get_status(mgr, invocation, ctx->status);
190
191         return TRUE;
192 }
193
194 static gboolean
195 on_nmea_getnmea(LbsNmea *nmea, GDBusMethodInvocation *invocation, gpointer user_data)
196 {
197         lbs_server_dbus_s *ctx = (lbs_server_dbus_s *)user_data;
198         if (!ctx)
199                 return FALSE;
200
201         gint timestamp = 0;
202         gchar *nmea_data = NULL;
203
204         if (ctx->get_nmea_cb) {
205                 ctx->get_nmea_cb(&timestamp, &nmea_data, ctx->userdata);
206                 LBS_SERVER_LOGD("timestmap: %d, nmea_data: %s", timestamp, nmea_data);
207         }
208         lbs_nmea_complete_get_nmea(nmea, invocation, timestamp, nmea_data);
209         g_free(nmea_data);
210
211         return TRUE;
212 }
213
214 static gboolean
215 on_manager_setoptions(LbsManager *mgr, GDBusMethodInvocation *invocation, GVariant *options, gpointer user_data)
216 {
217         LBS_SERVER_LOGD("ENTER >>>");
218         lbs_server_dbus_s *ctx = (lbs_server_dbus_s *)user_data;
219         if (!ctx)
220                 return FALSE;
221
222         if (ctx->set_options_cb) {
223                 const gchar *sender = NULL;
224                 sender = g_dbus_method_invocation_get_sender(invocation);
225                 ctx->set_options_cb(options, sender, ctx->userdata);
226                 LBS_SERVER_LOGD("set_options_cb was called");
227         }
228
229         lbs_manager_complete_set_options(mgr, invocation);
230
231         return TRUE;
232 }
233
234 static gboolean
235 on_manager_addreference(LbsManager *mgr, GDBusMethodInvocation *invocation, int method, gpointer user_data)
236 {
237         LBS_SERVER_LOGD("method: %d", method);
238         if (method < 0 || method >= LBS_SERVER_METHOD_SIZE) return FALSE;
239
240         lbs_server_dbus_s *ctx = (lbs_server_dbus_s *)user_data;
241         if (!ctx)
242                 return FALSE;
243
244         const gchar *sender = NULL;
245         gchar *sender_cp = NULL;
246         int count = 0;
247
248         /* Update the hash of open connections */
249         sender = g_dbus_method_invocation_get_sender(invocation);
250         sender_cp = g_strdup(sender);
251
252         int *count_arr = (int *) g_hash_table_lookup(ctx->connections, sender_cp);
253         if (!count_arr) {
254                 LBS_SERVER_LOGD("first add for sender %s ", sender_cp);
255                 count_arr = (int *)g_malloc0(LBS_SERVER_METHOD_SIZE * sizeof(int));
256                 g_return_val_if_fail(count_arr, FALSE);
257
258                 g_hash_table_insert(ctx->connections, (gpointer)sender_cp, (gpointer)count_arr);
259         }
260
261         count = count_arr[method];
262         count++;
263
264         if (count <= 0) {
265                 count = 1;
266                 LBS_SERVER_LOGE("Client reference count set to 1 for sender [%s] of method [%d]", sender_cp, method);
267         }
268
269         LBS_SERVER_LOGD("sender [%s], method[%d], count [%d] is inserted in hash table", sender_cp, method, count);
270
271         count_arr[method] = count;
272
273         lbs_manager_complete_add_reference(mgr, invocation);
274
275         return TRUE;
276 }
277
278 static gboolean lbs_find_method(gpointer key, gpointer value, gpointer user_data)
279 {
280         int *ip = (int *) user_data;
281         int *arr = (int *) value;
282         int method = *ip;
283
284         LBS_SERVER_LOGD("[%s] lbs_find_method method:%d, count:%d", (char *)key, method, arr[method]);
285
286         return (arr[method] > 0) ? TRUE : FALSE;
287 }
288
289 static gboolean
290 lbs_server_remove_client(lbs_server_dbus_s *ctx, const char *client, int method)
291 {
292         if (!ctx || !client)
293                 return FALSE;
294
295         int count = 0;
296         int *count_arr = (int *) g_hash_table_lookup(ctx->connections, client);
297
298         if (!count_arr) {
299                 LBS_SERVER_LOGD("Client[%s] Method[%d] is already removed", client, method);
300                 return FALSE;
301         }
302
303         count = count_arr[method];
304         LBS_SERVER_LOGD("lbs_server_remove_client method:%d count:%d", method, count);
305
306         if (count == 0) {
307                 LBS_SERVER_LOGD("Client[%s] Method[%d] is already removed", client, method);
308                 return FALSE;
309         }
310
311         count--;
312         count_arr[method] = count;
313
314         if (count > 0) {
315                 LBS_SERVER_LOGD("Client[%s] of method[%d] has reference count[%d]", client, method, count);
316         } else if (count == 0) {
317                 LBS_SERVER_LOGD("Remove [%s : %d] in hash table, ref count is 0", client, method);
318
319                 int i = 0, count_each = 0;
320                 for (i = 0; i < LBS_SERVER_METHOD_SIZE; i++) {
321                         count_each = count_arr[i];
322                         if (count_each != 0) {
323                                 LBS_SERVER_LOGD("[%s] method[%d]'s count is not zero - count: %d", client, i, count_each);
324                                 return FALSE;
325                         }
326                 }
327
328                 if (!g_hash_table_remove(ctx->connections, client))
329                         LBS_SERVER_LOGE("g_hash_table_remove is Fail");
330         }
331
332         int index = 0;
333         gboolean *shutdown_arr = (gboolean *) g_malloc0_n(LBS_SERVER_METHOD_SIZE, sizeof(gboolean));
334         g_return_val_if_fail(shutdown_arr, FALSE);
335
336         if (g_hash_table_size(ctx->connections) == 0) {
337                 LBS_SERVER_SECLOG("Hash table size is zero, Now shutdown provider[%s]", ctx->name);
338
339                 for (; index < LBS_SERVER_METHOD_SIZE; index++) shutdown_arr[index] = TRUE;
340         } else {
341                 LBS_SERVER_SECLOG("Hash table size is not zero");
342
343                 for (; index < LBS_SERVER_METHOD_SIZE ; index++) {
344                         if (g_hash_table_find(ctx->connections, (GHRFunc)lbs_find_method, &index) == NULL) {
345                                 shutdown_arr[index] = TRUE;
346                                 continue;
347                         }
348                 }
349         }
350
351         if (ctx->shutdown_cb) {
352                 ctx->shutdown_cb(ctx->userdata, shutdown_arr);
353                 LBS_SERVER_LOGD("shutdown_cb called.. gps:%d, nps:%d",
354                                                 shutdown_arr[LBS_SERVER_METHOD_GPS], shutdown_arr[LBS_SERVER_METHOD_NPS]);
355         }
356
357         g_free(shutdown_arr);
358         return TRUE;
359 }
360
361 static gboolean on_manager_removereference(LbsManager *mgr, GDBusMethodInvocation *invocation, int method, gpointer user_data)
362 {
363         LBS_SERVER_LOGD("method: %d", method);
364         if (method < 0 || method >= LBS_SERVER_METHOD_SIZE) return FALSE;
365
366         lbs_server_dbus_s *ctx = (lbs_server_dbus_s *)user_data;
367         if (!ctx)
368                 return FALSE;
369
370         const gchar *sender = NULL;
371         sender = g_dbus_method_invocation_get_sender(invocation);
372         if (!lbs_server_remove_client(ctx, sender, method))
373                 LBS_SERVER_LOGD("Unreffed by client that has not been referenced");
374
375         lbs_manager_complete_remove_reference(mgr, invocation);
376
377         return TRUE;
378 }
379
380 /*
381  * For H/W gps-geofence methods
382  */
383 static gboolean
384 on_gps_geofence_addfence(LbsGpsGeofence *gps_geofence,
385                                                  GDBusMethodInvocation *invocation,
386                                                  gint fence_id,
387                                                  gdouble latitude,
388                                                  gdouble longitude,
389                                                  gint radius,
390                                                  gint last_state,
391                                                  gint monitor_states,
392                                                  gint notification_responsiveness,
393                                                  gint unknown_timer,
394                                                  gpointer user_data)
395 {
396         LBS_SERVER_LOGD("on_gps_geofence_addfence");
397
398         /* call gps-manager's callback, add_hw_fence_cb */
399         lbs_server_dbus_s *ctx = (lbs_server_dbus_s *)user_data;
400         if (!ctx)
401                 return FALSE;
402
403         if (ctx->add_hw_fence_cb) {
404                 ctx->add_hw_fence_cb(fence_id, latitude, longitude, radius, last_state, monitor_states,
405                                                          notification_responsiveness, unknown_timer, ctx->userdata);
406                 LBS_SERVER_LOGD("add_hw_fence_cb called");
407         }
408         lbs_gps_geofence_complete_add_fence(gps_geofence, invocation);
409         return TRUE;
410 }
411
412 static gboolean
413 on_gps_geofence_deletefence(LbsGpsGeofence *gps_geofence, GDBusMethodInvocation *invocation, gint fence_id, gpointer user_data)
414 {
415         LBS_SERVER_LOGD("on_gps_geofence_deletefence");
416
417         /* call gps-manager's callback, delete_hw_fence_cb */
418         lbs_server_dbus_s *ctx = (lbs_server_dbus_s *)user_data;
419         if (!ctx)
420                 return FALSE;
421
422         if (ctx->delete_hw_fence_cb) {
423                 ctx->delete_hw_fence_cb(fence_id, ctx->userdata);
424                 LBS_SERVER_LOGD("delete_hw_fence_cb called");
425         }
426         lbs_gps_geofence_complete_delete_fence(gps_geofence, invocation);
427         return TRUE;
428 }
429
430 static gboolean
431 on_gps_geofence_pausefence(LbsGpsGeofence *gps_geofence, GDBusMethodInvocation *invocation, gint fence_id, gpointer user_data)
432 {
433         LBS_SERVER_LOGD("on_gps_geofence_pausefence");
434
435         /* call gps-manager's callback, pause_hw_fence_cb */
436         lbs_server_dbus_s *ctx = (lbs_server_dbus_s *)user_data;
437         if (!ctx)
438                 return FALSE;
439
440         if (ctx->pause_hw_fence_cb) {
441                 ctx->pause_hw_fence_cb(fence_id, ctx->userdata);
442                 LBS_SERVER_LOGD("pause_hw_fence_cb called");
443         }
444
445         lbs_gps_geofence_complete_pause_fence(gps_geofence, invocation);
446         return TRUE;
447 }
448
449 static gboolean
450 on_gps_geofence_resumefence(LbsGpsGeofence *gps_geofence, GDBusMethodInvocation *invocation, gint fence_id, gint monitor_states, gpointer user_data)
451 {
452         LBS_SERVER_LOGD("on_gps_geofence_resumefence");
453
454         lbs_server_dbus_s *ctx = (lbs_server_dbus_s *)user_data;
455         if (!ctx)
456                 return FALSE;
457
458         /* call gps-manager's callback, resume_hw_fence_cb */
459         if (ctx->resume_hw_fence_cb) {
460                 ctx->resume_hw_fence_cb(fence_id, monitor_states, ctx->userdata);
461                 LBS_SERVER_LOGD("resume_hw_fence_cb called");
462         }
463
464         lbs_gps_geofence_complete_resume_fence(gps_geofence, invocation);
465         return TRUE;
466 }
467
468
469 /* Tizen 3.0 */
470
471 static gboolean
472 on_manager_setmocklocation(LbsManager *mgr, GDBusMethodInvocation *invocation, gint method,
473                                                         gdouble latitude, gdouble longitude, gdouble altitude,
474                                                         gdouble speed, gdouble direction, gdouble accuracy, gpointer user_data)
475 {
476         LBS_SERVER_LOGD("on_manager_setmocklocation [method: %d]", method);
477         if (method < 0 || method >= LBS_SERVER_METHOD_SIZE) return FALSE;
478
479         lbs_server_dbus_s *ctx = (lbs_server_dbus_s *)user_data;
480         if (!ctx)
481                 return FALSE;
482
483         if (ctx->set_mock_location_cb) {
484                 ctx->set_mock_location_cb(method, latitude, longitude, altitude, speed, direction, accuracy, ctx->userdata);
485
486                 LBS_SERVER_LOGD("set_mock_location_cb was called");
487         }
488
489         lbs_manager_complete_set_mock_location(mgr, invocation);
490
491         return TRUE;
492 }
493
494 static gboolean
495 lbs_remove_client_by_force(const char *client, void *data)
496 {
497         LBS_SERVER_LOGD("remove client by force for client [%s]", client);
498         lbs_server_dbus_s *ctx = (lbs_server_dbus_s *)data;
499
500         int *count_arr = (int *) g_hash_table_lookup(ctx->connections, client);
501
502         if (!count_arr) {
503                 LBS_SERVER_LOGD("Client[%s] is already removed", client);
504                 return FALSE;
505         } else {
506                 LBS_SERVER_LOGD("[Client: %s]. Remove all clients in hash table", client);
507                 if (!g_hash_table_remove(ctx->connections, client))
508                         LBS_SERVER_LOGE("g_hash_table_remove is Fail");
509         }
510
511         int index = 0;
512         gboolean *shutdown_arr = (gboolean *) g_malloc0_n(LBS_SERVER_METHOD_SIZE, sizeof(gboolean));
513         g_return_val_if_fail(shutdown_arr, FALSE);
514
515         if (g_hash_table_size(ctx->connections) == 0) {
516                 LBS_SERVER_SECLOG("Hash table size is zero, Now shutdown provider[%s]", ctx->name);
517
518                 for (; index < LBS_SERVER_METHOD_SIZE; index++) shutdown_arr[index] = TRUE;
519         } else {
520                 LBS_SERVER_SECLOG("Hash table size is not zero");
521
522                 for (; index < LBS_SERVER_METHOD_SIZE ; index++) {
523                         if (g_hash_table_find(ctx->connections, (GHRFunc)lbs_find_method, &index) == NULL) {
524                                 shutdown_arr[index] = TRUE;
525                                 continue;
526                         }
527                 }
528         }
529
530         if (ctx->shutdown_cb) {
531                 ctx->shutdown_cb(ctx->userdata, shutdown_arr);
532                 LBS_SERVER_LOGD("shutdown_cb called.. gps:%d, nps:%d",
533                                                 shutdown_arr[LBS_SERVER_METHOD_GPS], shutdown_arr[LBS_SERVER_METHOD_NPS]);
534         }
535
536         if (ctx->update_interval_cb) {
537                 gboolean is_needed_change_interval = FALSE;
538                 for (index = 0; index < LBS_SERVER_METHOD_SIZE ; index++) {
539                         is_needed_change_interval = ctx->update_interval_cb(LBS_SERVER_INTERVAL_REMOVE, client, index, 0, 0, ctx->userdata);
540                         if (is_needed_change_interval) {
541                                 is_needed_change_interval = FALSE;
542                                 if (ctx->request_change_interval_cb)
543                                         ctx->request_change_interval_cb(index, ctx->userdata);
544                         }
545                 }
546
547         }
548
549         LBS_SERVER_LOGD("###### A client[%s] is abnormally shut down ########", client);
550
551         g_free(shutdown_arr);
552         return TRUE;
553 }
554
555 static void
556 lbs_scan_sender(char *key, char *value, gpointer user_data)
557 {
558         lbs_server_dbus_s *handle = (lbs_server_dbus_s *)user_data;
559         g_return_if_fail(handle);
560         gchar *prev_owner = handle->prev_owner;
561         g_return_if_fail(prev_owner);
562
563         if (g_strcmp0(prev_owner, key) == 0) {
564                 LBS_SERVER_LOGD("disconnected sender name matched, remove client by force!");
565                 lbs_remove_client_by_force(prev_owner, handle);
566         }
567 }
568
569 static void
570 on_name_owner_changed(GDBusConnection *connection,
571                                           const gchar *sender_name,
572                                           const gchar *object_path,
573                                           const gchar *interface_name,
574                                           const gchar *signal_name,
575                                           GVariant *parameters, /* 1. service name 2. prev_owner 3. new_owner */
576                                           gpointer user_data)
577 {
578         lbs_server_dbus_s *handle = (lbs_server_dbus_s *)user_data;
579         g_return_if_fail(handle);
580
581         gchar *service_name = NULL, *prev_owner = NULL, *new_owner = NULL;
582         g_variant_get(parameters, "(&s&s&s)", &service_name, &prev_owner, &new_owner);
583
584         if (g_strcmp0(object_path, "/org/freedesktop/DBus") != 0 ||
585                 g_strcmp0(interface_name, "org.freedesktop.DBus") != 0 ||
586                 g_strcmp0(sender_name, "org.freedesktop.DBus") != 0) {
587                 goto out;
588         }
589
590         /* if the prev_owner matches the sender name, then remote sender(client) is crashed */
591         if (g_strcmp0(new_owner, "") == 0 && (prev_owner != NULL && strlen(prev_owner) > 0)
592                 && handle->connections != NULL) {
593                 if (handle->prev_owner) {
594                         g_free(handle->prev_owner);
595                         handle->prev_owner = NULL;
596                 }
597                 handle->prev_owner = g_strdup(prev_owner);
598                 g_hash_table_foreach(handle->connections, (GHFunc)lbs_scan_sender, handle);
599         }
600
601 out:
602         ;
603 }
604
605 static void on_bus_acquired(GDBusConnection *conn, const gchar *name, gpointer user_data)
606 {
607         lbs_server_dbus_s *ctx = (lbs_server_dbus_s *)user_data;
608         if (!ctx)
609                 return;
610
611         LbsManager *mgr = NULL;
612         LbsObjectSkeleton *object = NULL;
613         gchar *path = NULL;
614
615         LBS_SERVER_LOGD("dbus registered");
616
617         /* create object for each interfaces*/
618         path = g_strdup_printf("%s/%s", ctx->service_path, "SAMSUNG");
619         if (path == NULL) {
620                 LBS_SERVER_LOGE("path is NULL");
621                 path = NULL;
622         }
623
624         object = lbs_object_skeleton_new(path);
625         if (object == NULL) {
626                 LBS_SERVER_LOGE("Can't create object. path: %s", path);
627                 g_free(path);
628                 return;
629         }
630         g_free(path);
631
632         ctx->obj_skeleton = object;
633         lbs_dbus_setup_position_interface(object, ctx);
634         lbs_dbus_setup_batch_interface(object, ctx);
635         lbs_dbus_setup_satellite_interface(object, ctx);
636         lbs_dbus_setup_nmea_interface(object, ctx);
637
638         /* add H/W gps-geofence interface */
639         lbs_dbus_setup_gps_geofence_interface(object, ctx);
640         g_dbus_object_manager_server_export(ctx->manager, G_DBUS_OBJECT_SKELETON(object));
641
642         /* Add interface to default object path */
643         mgr = lbs_manager_skeleton_new();
644
645         ctx->get_providerinfo_h = g_signal_connect(mgr, "handle-get-provider-info", G_CALLBACK(on_manager_getproviderinfo), ctx);
646         ctx->get_status_h = g_signal_connect(mgr, "handle-get-status", G_CALLBACK(on_manager_getstatus), ctx);
647         if (ctx->set_options_cb != NULL)
648                 ctx->set_option_h = g_signal_connect(mgr, "handle-set-options", G_CALLBACK(on_manager_setoptions), ctx);
649
650         ctx->add_reference_h = g_signal_connect(mgr, "handle-add-reference", G_CALLBACK(on_manager_addreference), ctx);
651         if (ctx->shutdown_cb)
652                 ctx->remove_reference_h = g_signal_connect(mgr, "handle-remove-reference", G_CALLBACK(on_manager_removereference), ctx);
653
654         /* Tizen 3.0 */
655         if (ctx->set_mock_location_cb)
656                 ctx->set_mock_location_h = g_signal_connect(mgr, "handle-set-mock-location", G_CALLBACK(on_manager_setmocklocation), ctx);
657
658         /* Add interface for nmea method*/
659         LbsNmea *nmea = NULL;
660         nmea = lbs_nmea_skeleton_new();
661         ctx->get_nmea_h = g_signal_connect(nmea, "handle-get-nmea", G_CALLBACK(on_nmea_getnmea), ctx);
662
663         /* register callback for each methods for H/W gps-geofence */
664         LbsGpsGeofence *gps_geofence = NULL;
665         if (ctx->obj_skeleton) {
666                 gps_geofence = lbs_object_get_gps_geofence(LBS_OBJECT(ctx->obj_skeleton));
667                 if (gps_geofence) {
668                         if (ctx->add_hw_fence_cb)
669                                 ctx->add_hw_fence_h = g_signal_connect(gps_geofence, "handle-add-fence", G_CALLBACK(on_gps_geofence_addfence), ctx);
670
671                         if (ctx->delete_hw_fence_cb)
672                                 ctx->delete_hw_fence_h = g_signal_connect(gps_geofence, "handle-delete-fence", G_CALLBACK(on_gps_geofence_deletefence), ctx);
673
674                         if (ctx->pause_hw_fence_cb)
675                                 ctx->pause_hw_fence_h = g_signal_connect(gps_geofence, "handle-pause-fence", G_CALLBACK(on_gps_geofence_pausefence), ctx);
676
677                         if (ctx->resume_hw_fence_cb)
678                                 ctx->resume_hw_fence_h = g_signal_connect(gps_geofence, "handle-resume-fence", G_CALLBACK(on_gps_geofence_resumefence), ctx);
679
680                         g_object_unref(gps_geofence);
681                 }
682         }
683
684         ctx->owner_changed_id = g_dbus_connection_signal_subscribe(conn,
685                                                    "org.freedesktop.DBus", "org.freedesktop.DBus", "NameOwnerChanged", "/org/freedesktop/DBus", NULL,
686                                                    G_DBUS_SIGNAL_FLAGS_NONE, on_name_owner_changed, ctx, NULL);
687
688         g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(mgr), conn, ctx->service_path, NULL);
689         g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(nmea), conn, ctx->service_path, NULL);
690
691         g_dbus_object_manager_server_set_connection(ctx->manager, conn);
692
693         LBS_SERVER_LOGD("done to acquire the dbus");
694 }
695
696 static void on_name_acquired(GDBusConnection *connection, const gchar *name, gpointer user_data)
697 {
698         LBS_SERVER_SECLOG("LBS Server: Acquired the name <%s> on the system bus", name);
699 }
700
701 static void on_name_lost(GDBusConnection *connection, const gchar *name, gpointer user_data)
702 {
703         LBS_SERVER_SECLOG("LBS Server: Lost the name <%s> on the system bus", name);
704 }
705
706 EXPORT_API int
707 lbs_server_emit_position_changed(lbs_server_dbus_h lbs_server,
708                                                                 gint arg_method, gint arg_fields, gint arg_timestamp, gdouble arg_latitude, gdouble arg_longitude, gdouble arg_altitude,
709                                                                 gdouble arg_speed, gdouble arg_direction, gdouble arg_climb, GVariant *arg_accuracy)
710 {
711         g_return_val_if_fail(lbs_server, LBS_SERVER_ERROR_PARAMETER);
712         g_return_val_if_fail(arg_accuracy, LBS_SERVER_ERROR_PARAMETER);
713
714         lbs_server_dbus_s *handle = (lbs_server_dbus_s *)lbs_server;
715         g_return_val_if_fail(handle->obj_skeleton, LBS_SERVER_ERROR_PARAMETER);
716
717         LbsPosition *lbs_pos = NULL;
718         lbs_pos = lbs_object_get_position(LBS_OBJECT(handle->obj_skeleton));
719         g_return_val_if_fail(lbs_pos, LBS_SERVER_ERROR_PARAMETER);
720
721         lbs_position_emit_position_changed(lbs_pos,
722            arg_method, arg_fields, arg_timestamp, arg_latitude, arg_longitude, arg_altitude, arg_speed, arg_direction, arg_climb, arg_accuracy);
723
724         g_object_unref(lbs_pos);
725
726         return LBS_SERVER_ERROR_NONE;
727
728 }
729
730 EXPORT_API int
731 lbs_server_emit_batch_changed(lbs_server_dbus_h lbs_server, gint arg_num_of_location)
732 {
733         g_return_val_if_fail(lbs_server, LBS_SERVER_ERROR_PARAMETER);
734
735         lbs_server_dbus_s *handle = (lbs_server_dbus_s *)lbs_server;
736         g_return_val_if_fail(handle->obj_skeleton, LBS_SERVER_ERROR_PARAMETER);
737
738         LbsBatch *lbs_batch = NULL;
739         lbs_batch = lbs_object_get_batch(LBS_OBJECT(handle->obj_skeleton));
740         g_return_val_if_fail(lbs_batch, LBS_SERVER_ERROR_PARAMETER);
741
742         lbs_batch_emit_batch_changed(lbs_batch, arg_num_of_location);
743
744         g_object_unref(lbs_batch);
745
746         return LBS_SERVER_ERROR_NONE;
747 }
748
749 EXPORT_API int
750 lbs_server_emit_satellite_changed(lbs_server_dbus_h lbs_server, gint arg_timestamp, gint arg_satellite_used, gint arg_satellite_visible, GVariant *arg_used_prn, GVariant *arg_sat_info)
751 {
752         g_return_val_if_fail(lbs_server, LBS_SERVER_ERROR_PARAMETER);
753         g_return_val_if_fail(arg_used_prn, LBS_SERVER_ERROR_PARAMETER);
754         g_return_val_if_fail(arg_sat_info, LBS_SERVER_ERROR_PARAMETER);
755
756         lbs_server_dbus_s *handle = (lbs_server_dbus_s *)lbs_server;
757         g_return_val_if_fail(handle->obj_skeleton, LBS_SERVER_ERROR_PARAMETER);
758
759         LbsSatellite *sat = NULL;
760         sat = lbs_object_get_satellite(LBS_OBJECT(handle->obj_skeleton));
761         g_return_val_if_fail(sat, LBS_SERVER_ERROR_PARAMETER);
762
763         lbs_satellite_emit_satellite_changed(sat, arg_timestamp, arg_satellite_used, arg_satellite_visible, arg_used_prn, arg_sat_info);
764         g_object_unref(sat);
765
766         return LBS_SERVER_ERROR_NONE;
767 }
768
769 EXPORT_API int
770 lbs_server_emit_nmea_changed(lbs_server_dbus_h lbs_server, gint arg_timestamp, const gchar *arg_nmea_data)
771 {
772         LBS_SERVER_LOGW("timestamp: %d, nmea_data: %s", arg_timestamp, arg_nmea_data);
773
774         g_return_val_if_fail(lbs_server, LBS_SERVER_ERROR_PARAMETER);
775         g_return_val_if_fail(arg_nmea_data, LBS_SERVER_ERROR_PARAMETER);
776
777         lbs_server_dbus_s *handle = (lbs_server_dbus_s *)lbs_server;
778         g_return_val_if_fail(handle->obj_skeleton, LBS_SERVER_ERROR_PARAMETER);
779
780         LbsNmea *nmea = NULL;
781         nmea = lbs_object_get_nmea(LBS_OBJECT(handle->obj_skeleton));
782         g_return_val_if_fail(nmea, LBS_SERVER_ERROR_PARAMETER);
783
784         lbs_nmea_emit_nmea_changed(nmea, arg_timestamp, arg_nmea_data);
785         g_object_unref(nmea);
786
787         return LBS_SERVER_ERROR_NONE;
788 }
789
790 EXPORT_API int
791 lbs_server_emit_status_changed(lbs_server_dbus_h lbs_server, int method, gint status)
792 {
793         LBS_SERVER_LOGD("method: %d, status: %d", method, status);
794         g_return_val_if_fail(lbs_server, LBS_SERVER_ERROR_PARAMETER);
795
796         lbs_server_dbus_s *handle = (lbs_server_dbus_s *)lbs_server;
797         g_return_val_if_fail(handle->obj_skeleton, LBS_SERVER_ERROR_PARAMETER);
798
799         LbsManager *lbs_mgr = NULL;
800         lbs_mgr = lbs_object_get_manager(LBS_OBJECT(handle->obj_skeleton));
801         g_return_val_if_fail(lbs_mgr, LBS_SERVER_ERROR_PARAMETER);
802
803         handle->status = status;
804         lbs_manager_emit_status_changed(lbs_mgr, method, status);
805         g_object_unref(lbs_mgr);
806
807         return LBS_SERVER_ERROR_NONE;
808 }
809
810 /* gps-manager -> geofence-manager : enable/disable */
811 EXPORT_API int
812 lbs_server_emit_gps_geofence_status_changed(lbs_server_dbus_h lbs_server, gint status)
813 {
814         LBS_SERVER_LOGD("ENTER >>>");
815         g_return_val_if_fail(lbs_server, LBS_SERVER_ERROR_PARAMETER);
816
817         lbs_server_dbus_s *handle = (lbs_server_dbus_s *)lbs_server;
818         g_return_val_if_fail(handle->obj_skeleton, LBS_SERVER_ERROR_PARAMETER);
819
820         LbsGpsGeofence *gps_geofence = NULL;
821         gps_geofence = lbs_object_get_gps_geofence(LBS_OBJECT(handle->obj_skeleton));
822         g_return_val_if_fail(gps_geofence, LBS_SERVER_ERROR_PARAMETER);
823
824         handle->hw_geofence_status = status;
825         lbs_gps_geofence_emit_status_changed(gps_geofence, status);
826         g_object_unref(gps_geofence);
827
828         return LBS_SERVER_ERROR_NONE;
829 }
830
831 /* gps-manager -> geofence-manger: fence in/out */
832 EXPORT_API int
833 lbs_server_emit_gps_geofence_changed(lbs_server_dbus_h lbs_server, gint fence_id, gint transition, gdouble latitude, gdouble longitude, gdouble altitude, gdouble speed, gdouble bearing, gdouble hor_accuracy)
834 {
835         LBS_SERVER_LOGD("ENTER >>>");
836         g_return_val_if_fail(lbs_server, LBS_SERVER_ERROR_PARAMETER);
837
838         lbs_server_dbus_s *handle = (lbs_server_dbus_s *)lbs_server;
839         g_return_val_if_fail(handle->obj_skeleton, LBS_SERVER_ERROR_PARAMETER);
840
841         LbsGpsGeofence *gps_geofence = NULL;
842         gps_geofence = lbs_object_get_gps_geofence(LBS_OBJECT(handle->obj_skeleton));
843         g_return_val_if_fail(gps_geofence, LBS_SERVER_ERROR_PARAMETER);
844
845         lbs_gps_geofence_emit_geofence_changed(gps_geofence, fence_id, transition, latitude, longitude, altitude, speed, bearing, hor_accuracy);
846         g_object_unref(gps_geofence);
847
848         return LBS_SERVER_ERROR_NONE;
849 }
850
851 static void _glib_log(const gchar *log_domain, GLogLevelFlags log_level, const gchar *msg, gpointer user_data)
852 {
853         LBS_SERVER_LOGD("GLIB[%d]: %s", log_level, msg);
854 }
855
856 EXPORT_API int
857 lbs_server_create(char *service_name, char *service_path, char *name, char *description, lbs_server_dbus_h *lbs_server, lbs_server_dbus_cb_t *lbs_server_cb, gpointer userdata)
858 {
859         LBS_SERVER_LOGD("ENTER >>>");
860         g_return_val_if_fail(service_name, LBS_SERVER_ERROR_PARAMETER);
861         g_return_val_if_fail(service_path, LBS_SERVER_ERROR_PARAMETER);
862         g_return_val_if_fail(lbs_server, LBS_SERVER_ERROR_PARAMETER);
863
864         int ret = LBS_SERVER_ERROR_NONE;
865
866         lbs_server_dbus_s *server = g_new0(lbs_server_dbus_s, 1);
867         g_return_val_if_fail(server, LBS_SERVER_ERROR_MEMORY);
868
869         g_log_set_default_handler(_glib_log, NULL);
870
871         server->service_name = g_strdup(service_name);
872         server->service_path = g_strdup(service_path);
873         server->manager = g_dbus_object_manager_server_new(server->service_path);
874
875         if (name)
876                 server->name = g_strdup(name);
877
878         if (description)
879                 server->description = g_strdup(description);
880
881         server->connections = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
882         server->userdata = userdata;
883
884 #if TIZEN_3_0_OPT
885         server->callback = lbs_server_cb;
886 #endif
887
888         server->set_options_cb = lbs_server_cb->set_options_cb;
889         server->shutdown_cb = lbs_server_cb->shutdown_cb;
890         server->update_interval_cb = lbs_server_cb->update_interval_cb;
891         server->request_change_interval_cb = lbs_server_cb->request_change_interval_cb;
892         server->get_nmea_cb = lbs_server_cb->get_nmea_cb;
893
894         /* Tizen 3.0 */
895         server->set_mock_location_cb = lbs_server_cb->set_mock_location_cb;
896
897         /* add H/W gps-gefence callbacks */
898         server->add_hw_fence_cb = lbs_server_cb->add_hw_fence_cb;
899         server->delete_hw_fence_cb = lbs_server_cb->delete_hw_fence_cb;
900         server->pause_hw_fence_cb = lbs_server_cb->pause_hw_fence_cb;
901         server->resume_hw_fence_cb = lbs_server_cb->resume_hw_fence_cb;
902         server->owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
903                                                   service_name, G_BUS_NAME_OWNER_FLAGS_REPLACE, on_bus_acquired, on_name_acquired, on_name_lost, server, NULL);
904
905         LBS_SERVER_LOGD("g_bus_own_name id=[%d]", server->owner_id);
906
907         *lbs_server = (lbs_server_dbus_h *)server;
908
909         return ret;
910 }
911
912
913 EXPORT_API int
914 lbs_server_destroy(lbs_server_dbus_h lbs_server)
915 {
916         LBS_SERVER_LOGD("ENTER >>>");
917         g_return_val_if_fail(lbs_server, LBS_SERVER_ERROR_PARAMETER);
918
919         lbs_server_dbus_s *handle = (lbs_server_dbus_s *)lbs_server;
920
921         int ret = LBS_SERVER_ERROR_NONE;
922
923         g_bus_unown_name(handle->owner_id);
924
925         if (handle->prev_owner) {
926                 g_free(handle->prev_owner);
927                 handle->prev_owner = NULL;
928         }
929
930         LbsManager *lbs_mgr = NULL;
931         lbs_mgr = lbs_object_get_manager(LBS_OBJECT(handle->obj_skeleton));
932         g_return_val_if_fail(lbs_mgr, LBS_SERVER_ERROR_PARAMETER);
933
934         if (handle->get_providerinfo_h) {
935                 g_signal_handler_disconnect(lbs_mgr, handle->get_providerinfo_h);
936                 handle->get_providerinfo_h = 0;
937         }
938
939         if (handle->get_status_h) {
940                 g_signal_handler_disconnect(lbs_mgr, handle->get_status_h);
941                 handle->get_status_h = 0;
942         }
943
944         if (handle->set_option_h) {
945                 g_signal_handler_disconnect(lbs_mgr, handle->set_option_h);
946                 handle->set_option_h = 0;
947         }
948
949         if (handle->add_reference_h) {
950                 g_signal_handler_disconnect(lbs_mgr, handle->add_reference_h);
951                 handle->add_reference_h = 0;
952         }
953
954         if (handle->remove_reference_h) {
955                 g_signal_handler_disconnect(lbs_mgr, handle->remove_reference_h);
956                 handle->remove_reference_h = 0;
957         }
958
959         if (handle->set_mock_location_h) {
960                 g_signal_handler_disconnect(lbs_mgr, handle->set_mock_location_h);
961                 handle->set_mock_location_h = 0;
962         }
963         g_object_unref(lbs_mgr);
964
965         LbsNmea *nmea = NULL;
966         nmea = lbs_object_get_nmea(LBS_OBJECT(handle->obj_skeleton));
967         g_return_val_if_fail(nmea, LBS_SERVER_ERROR_PARAMETER);
968
969         if (handle->get_nmea_h) {
970                 g_signal_handler_disconnect(nmea, handle->get_nmea_h);
971                 handle->get_nmea_h = 0;
972         }
973         g_object_unref(nmea);
974
975         /* disconnect H/W gps-geofence callbacks */
976         LbsGpsGeofence *gps_geofence = NULL;
977         gps_geofence = lbs_object_get_gps_geofence(LBS_OBJECT(handle->obj_skeleton));
978         g_return_val_if_fail(gps_geofence, LBS_SERVER_ERROR_PARAMETER);
979
980         if (handle->add_hw_fence_h) {
981                 g_signal_handler_disconnect(gps_geofence, handle->add_hw_fence_h);
982                 handle->add_hw_fence_h = 0;
983         }
984
985         if (handle->delete_hw_fence_h) {
986                 g_signal_handler_disconnect(gps_geofence, handle->delete_hw_fence_h);
987                 handle->delete_hw_fence_h = 0;
988         }
989
990         if (handle->pause_hw_fence_h) {
991                 g_signal_handler_disconnect(gps_geofence, handle->pause_hw_fence_h);
992                 handle->pause_hw_fence_h = 0;
993         }
994
995         if (handle->resume_hw_fence_h) {
996                 g_signal_handler_disconnect(gps_geofence, handle->resume_hw_fence_h);
997                 handle->resume_hw_fence_h = 0;
998         }
999
1000         g_object_unref(gps_geofence);
1001
1002         if (handle->manager) {
1003                 if (handle->owner_changed_id) {
1004                         g_dbus_connection_signal_unsubscribe(g_dbus_object_manager_server_get_connection(handle->manager), handle->owner_changed_id);
1005                         handle->owner_changed_id = 0;
1006                 }
1007                 g_object_unref(handle->manager);
1008                 handle->manager = NULL;
1009         }
1010
1011         g_hash_table_destroy(handle->connections);
1012
1013         g_free(handle);
1014
1015         return ret;
1016 }
1017