1. fixed that mock-location makes lbs-server crashed
[platform/core/location/lbs-dbus.git] / client / src / lbs_dbus_client.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 #include <app_manager.h>
24 #include <package_manager.h>
25 #include "lbs_dbus_client.h"
26 #include "lbs_dbus_client_priv.h"
27 #include "generated-code.h"
28
29 #define LOCATION_PRIVACY_ID     "http://tizen.org/privacy/location"
30 #define PRIVACY_INTERFACE       "org.tizen.privacy_manager.signal"
31 #define PRIVACY_MEMBER          "privacy_setting_changed"
32 #define PRIVACY_PATH            "/privacy_manager/dbus_notification"
33
34 typedef struct _lbs_client_dbus_s {
35         int is_started;
36         GDBusConnection *conn;
37         lbs_client_method_e method;
38         int loc_evt_id;
39         int loc_status_evt_id;
40         int sat_evt_id;
41         int batch_evt_id;
42         int nmea_evt_id;
43         int privacy_evt_id;
44         lbs_client_cb user_cb;
45         lbs_client_cb batch_cb;
46         lbs_client_cb set_mock_cb;
47         void *user_data;
48 } lbs_client_dbus_s;
49
50 static int __lbs_get_appid(char **app_id)
51 {
52         pid_t pid = getpid();
53         int ret = 0;
54         char *aid = NULL;
55
56         ret = app_manager_get_app_id(pid, &aid);
57         if (ret != APP_MANAGER_ERROR_NONE || aid == NULL) {
58                 LBS_CLIENT_LOGE("Fail to app_manager_get_package. Error[%d]", ret);
59                 return FALSE;
60         }
61         *app_id = (char *)g_malloc0(sizeof(char) * 64);
62         g_strlcpy(*app_id, aid, 64);
63         LBS_CLIENT_LOGD("get_appid %s", *app_id);
64         g_free(aid);
65
66         return TRUE;
67 }
68
69 static int __lbs_get_app_type(char *app_id, char **type)
70 {
71         int ret;
72         app_info_h app_info;
73         char *app_type = NULL;
74
75         ret = app_info_create(app_id, &app_info);
76         if (ret != APP_MANAGER_ERROR_NONE) {
77                 LBS_CLIENT_LOGE("Fail to get app_info. Err[%d]", ret);
78                 return FALSE;
79         }
80
81         ret = app_info_get_type(app_info, &app_type);
82         if (ret != APP_MANAGER_ERROR_NONE) {
83                 LBS_CLIENT_LOGE("Fail to get type. Err[%d]", ret);
84                 app_info_destroy(app_info);
85                 return FALSE;
86         }
87
88         *type = (char *)g_malloc0(sizeof(char) * 16);
89         g_strlcpy(*type, app_type, 16);
90         g_free(app_type);
91         app_info_destroy(app_info);
92
93         return TRUE;
94 }
95
96 static int __lbs_check_package_id(char *pkg_id)
97 {
98         int ret;
99         gchar *app_id = NULL;
100         gchar *type = NULL;
101         char *package_id = NULL;
102
103         if (!__lbs_get_appid(&app_id))
104                 return FALSE;
105
106         if (!__lbs_get_app_type(app_id, &type))
107                 return FALSE;
108
109         if ((g_strcmp0(type, "c++app") == 0) || (g_strcmp0(type, "webapp") == 0)) {
110                 LBS_CLIENT_LOGE("Do not check for App[%s] Type[%s]", app_id, type);
111                 g_free(app_id);
112                 g_free(type);
113                 return FALSE;
114         }
115         g_free(type);
116
117         ret = package_manager_get_package_id_by_app_id(app_id, &package_id);
118         if (ret != PACKAGE_MANAGER_ERROR_NONE) {
119                 LBS_CLIENT_LOGE("Fail to get package_id for [%s]. Err[%d]", app_id, ret);
120                 g_free(app_id);
121                 return FALSE;
122         }
123         LBS_CLIENT_LOGD("Current package[%s] / Privacy package[%s]", package_id, pkg_id);
124
125         if (g_strcmp0(pkg_id, package_id) == 0)
126                 ret = TRUE;
127         else
128                 ret = FALSE;
129
130         g_free(package_id);
131         g_free(app_id);
132
133         return ret;
134 }
135
136
137 static void __signal_batch_callback(GDBusConnection *conn, const gchar *name, const gchar *path, const gchar *interface, const gchar *sig, GVariant *param, gpointer user_data)
138 {
139         lbs_client_dbus_s *handle = (lbs_client_dbus_s *)user_data;
140         if (handle == NULL) {
141                 LBS_CLIENT_LOGD("Invalid handle");
142                 return;
143         }
144
145         if (handle->is_started == FALSE) {
146                 LBS_CLIENT_LOGD("Handle[%p] is not started", handle);
147                 return;
148         }
149
150         if (handle->batch_cb)
151                 handle->batch_cb(sig, param, handle->user_data);
152 }
153
154 static void __signal_callback(GDBusConnection *conn, const gchar *name, const gchar *path, const gchar *interface, const gchar *sig, GVariant *param, gpointer user_data)
155 {
156         lbs_client_dbus_s *handle = (lbs_client_dbus_s *)user_data;
157         if (handle == NULL) {
158                 LBS_CLIENT_LOGD("Invalid handle");
159                 return;
160         }
161
162         if (handle->is_started == FALSE) {
163                 LBS_CLIENT_LOGD("Handle[%p] is not started", handle);
164                 return;
165         }
166
167         if (handle->user_cb)
168                 handle->user_cb(sig, param, handle->user_data);
169 }
170
171 static void __privacy_setting_changed(GDBusConnection *conn, const gchar *name, const gchar *path, const gchar *interface, const gchar *sig, GVariant *param, gpointer user_data)
172 {
173         LBS_CLIENT_LOGD("ENTER >>>");
174
175         gchar *pkg_id = NULL;
176         gchar *privacy_id = NULL;
177
178         g_variant_get(param, "(ss)", &pkg_id, &privacy_id);
179         if (!pkg_id)
180                 return;
181
182         if (!privacy_id) {
183                 g_free(pkg_id);
184                 return;
185         }
186
187         if (g_strcmp0(privacy_id, LOCATION_PRIVACY_ID) != 0) {
188                 LBS_CLIENT_LOGD("[%s]'s [%s] privacy is changed", pkg_id, privacy_id);
189                 g_free(pkg_id);
190                 g_free(privacy_id);
191                 return;
192         }
193
194         LBS_CLIENT_LOGD("[%s]'s [%s] location privacy is changed", pkg_id, privacy_id);
195         lbs_client_dbus_s *handle = (lbs_client_dbus_s *)user_data;
196
197         if (handle == NULL || handle->is_started == FALSE) {
198                 LBS_CLIENT_LOGE("Invalid handle or is_started [FALSE]");
199                 g_free(pkg_id);
200                 g_free(privacy_id);
201                 return;
202         }
203
204         if (!__lbs_check_package_id(pkg_id)) {
205                 LBS_CLIENT_LOGE("pkg_id[%s] is not current pakcage id", pkg_id);
206                 g_free(pkg_id);
207                 g_free(privacy_id);
208                 return;
209         }
210         g_free(pkg_id);
211         g_free(privacy_id);
212
213         if (lbs_client_stop(handle) != LBS_CLIENT_ERROR_NONE)
214                 LBS_CLIENT_LOGE("lbs_client_stop is fail");
215
216         if (handle->user_cb)
217                 handle->user_cb("StatusChanged", g_variant_new("(i)", FALSE), handle->user_data);
218
219         lbs_client_destroy(handle);
220         handle = NULL;
221
222         LBS_CLIENT_LOGD("EXIT <<<");
223 }
224
225 static void
226 lbs_client_signal_unsubcribe(lbs_client_dbus_h lbs_client)
227 {
228         LBS_CLIENT_LOGD("lbs_client_unsubcribe");
229
230         lbs_client_dbus_s *handle = (lbs_client_dbus_s *)lbs_client;
231         if (handle == NULL) {
232                 LBS_CLIENT_LOGD("Invalid handle");
233                 return;
234         }
235         if (handle->conn == NULL) {
236                 LBS_CLIENT_LOGD("Invalid dbus_connection");
237                 return;
238         }
239
240         if (handle->loc_evt_id) {
241                 g_dbus_connection_signal_unsubscribe(handle->conn, handle->loc_evt_id);
242                 handle->loc_evt_id = 0;
243         }
244
245         if (handle->batch_evt_id) {
246                 g_dbus_connection_signal_unsubscribe(handle->conn, handle->batch_evt_id);
247                 handle->batch_evt_id = 0;
248         }
249
250         if (handle->sat_evt_id) {
251                 g_dbus_connection_signal_unsubscribe(handle->conn, handle->sat_evt_id);
252                 handle->sat_evt_id = 0;
253         }
254
255         if (handle->loc_status_evt_id) {
256                 g_dbus_connection_signal_unsubscribe(handle->conn, handle->loc_status_evt_id);
257                 handle->loc_status_evt_id = 0;
258         }
259
260         if (handle->nmea_evt_id) {
261                 g_dbus_connection_signal_unsubscribe(handle->conn, handle->nmea_evt_id);
262                 handle->nmea_evt_id = 0;
263         }
264 }
265
266 static void
267 lbs_client_privacy_signal_subcribe(lbs_client_dbus_h lbs_client)
268 {
269         LBS_CLIENT_LOGD("lbs_client_privacy_signal_subcribe");
270
271         lbs_client_dbus_s *handle = (lbs_client_dbus_s *)lbs_client;
272         handle->privacy_evt_id = g_dbus_connection_signal_subscribe(handle->conn,
273                                                                 NULL, PRIVACY_INTERFACE, PRIVACY_MEMBER, PRIVACY_PATH, NULL, G_DBUS_SIGNAL_FLAGS_NONE, __privacy_setting_changed, handle, NULL);
274
275         if (handle->privacy_evt_id)
276                 LBS_CLIENT_LOGD("Listening Privacy info");
277         else
278                 LBS_CLIENT_LOGD("Fail to listen Privacy info");
279 }
280
281 static void
282 lbs_client_privacy_signal_unsubcribe(lbs_client_dbus_h lbs_client)
283 {
284         LBS_CLIENT_LOGD("lbs_client_privacy_signal_unsubcribe");
285
286         lbs_client_dbus_s *handle = (lbs_client_dbus_s *)lbs_client;
287         if (handle->privacy_evt_id) {
288                 g_dbus_connection_signal_unsubscribe(handle->conn, handle->privacy_evt_id);
289                 handle->privacy_evt_id = 0;
290         }
291 }
292
293 EXPORT_API int
294 lbs_client_batch_start(lbs_client_dbus_h lbs_client, lbs_client_callback_e callback_type, lbs_client_cb callback, unsigned int batch_interval, unsigned int batch_period, void *user_data)
295 {
296         LBS_CLIENT_LOGD("lbs_client_batch_start");
297
298         g_return_val_if_fail(lbs_client, LBS_CLIENT_ERROR_PARAMETER);
299         g_return_val_if_fail(callback_type >= LBS_CLIENT_LOCATION_CB && callback_type <= LBS_CLIENT_BATCH_CB, LBS_CLIENT_ERROR_PARAMETER);
300
301         lbs_client_dbus_s *handle = (lbs_client_dbus_s *)lbs_client;
302         g_return_val_if_fail(handle->is_started == FALSE, LBS_CLIENT_ERROR_STATUS);
303
304         GVariant *reg = NULL;
305         GVariant *param = NULL, *method = NULL;
306         GError *error = NULL;
307         GVariantBuilder *builder = NULL;
308         GDBusProxy *proxy = NULL;
309         gchar *signal_path = NULL;
310         int ret = LBS_CLIENT_ERROR_NONE;
311
312         signal_path = g_strdup_printf("%s/%s", SERVICE_PATH, "SAMSUNG");
313         LBS_CLIENT_SECLOG("LBS signal subscribe Object Path [%s]", signal_path);
314
315         if (callback) {
316                 handle->batch_cb = callback;
317                 handle->user_data = user_data;
318
319                 if (callback_type & LBS_CLIENT_BATCH_CB) {
320                         handle->batch_evt_id = g_dbus_connection_signal_subscribe(handle->conn,
321                                                                           SERVICE_NAME, "org.tizen.lbs.Batch", "BatchChanged",
322                                                                           signal_path, NULL, G_DBUS_SIGNAL_FLAGS_NONE, __signal_batch_callback, handle, NULL);
323
324                         if (handle->batch_evt_id)
325                                 LBS_CLIENT_LOGD("Listening batch info");
326                         else
327                                 LBS_CLIENT_LOGD("Fail to listen batch info");
328                 }
329         }
330         g_free(signal_path);
331
332         /* Start Batch */
333         LBS_CLIENT_LOGD("START: CMD-START_BATCH");
334         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
335         g_variant_builder_add(builder, "{sv}", "CMD", g_variant_new_string("START_BATCH"));
336         g_variant_builder_add(builder, "{sv}", "BATCH_INTERVAL", g_variant_new_int32((gint32) batch_interval));
337         g_variant_builder_add(builder, "{sv}", "BATCH_PERIOD", g_variant_new_int32((gint32) batch_period));
338         param = g_variant_ref_sink(g_variant_new("(@a{sv})", g_variant_builder_end(builder)));
339         method = g_variant_ref_sink(g_variant_new("(i)", handle->method));
340
341         proxy = g_dbus_proxy_new_sync(handle->conn,  /* GDBusConnection */
342                                                                   G_DBUS_PROXY_FLAGS_NONE, /*GDbusProxyFlags */
343                                                                   NULL,
344                                                                   SERVICE_NAME, SERVICE_PATH,
345                                                                   "org.tizen.lbs.Manager",
346                                                                   NULL,
347                                                                   &error);
348
349         if (error && error->message) {
350                 if (error->code == G_DBUS_ERROR_ACCESS_DENIED) {
351                         LBS_CLIENT_LOGE("Access denied. Msg[%s]", error->message);
352                         ret = LBS_CLIENT_ERROR_ACCESS_DENIED;
353                 } else {
354                         LBS_CLIENT_LOGE("Fail to new proxy ErrCode[%d], Msg[%s]", error->code, error->message);
355                         ret = LBS_CLIENT_ERROR_DBUS_CALL;
356                 }
357                 g_error_free(error);
358                 g_variant_unref(param);
359                 g_variant_unref(method);
360                 lbs_client_signal_unsubcribe(handle);
361                 return ret;
362         }
363
364         if (proxy) {
365                 reg = g_dbus_proxy_call_sync(proxy, "AddReference", method, G_DBUS_CALL_FLAGS_NONE, -1, NULL,
366                                                                          &error);
367
368                 if (error && error->message) {
369                         if (error->code == G_DBUS_ERROR_ACCESS_DENIED) {
370                                 LBS_CLIENT_LOGE("Access denied. Msg[%s]", error->message);
371                                 ret = LBS_CLIENT_ERROR_ACCESS_DENIED;
372                         } else {
373                                 LBS_CLIENT_LOGE("Fail to new proxy ErrCode[%d], Msg[%s]", error->code, error->message);
374                                 ret = LBS_CLIENT_ERROR_DBUS_CALL;
375                         }
376                         g_error_free(error);
377                         g_variant_unref(param);
378                         g_variant_unref(method);
379                         lbs_client_signal_unsubcribe(handle);
380                         return ret;
381                 }
382                 if (reg) {
383                         g_variant_unref(reg);
384                         reg = NULL;
385                 }
386
387                 reg = g_dbus_proxy_call_sync(proxy, "SetOptions", param, G_DBUS_CALL_FLAGS_NO_AUTO_START, -1, NULL, &error);
388
389                 if (error && error->message) {
390                         if (error->code == G_DBUS_ERROR_ACCESS_DENIED) {
391                                 LBS_CLIENT_LOGE("Access denied. Msg[%s]", error->message);
392                                 ret = LBS_CLIENT_ERROR_ACCESS_DENIED;
393                         } else {
394                                 LBS_CLIENT_LOGE("Fail to new proxy ErrCode[%d], Msg[%s]", error->code, error->message);
395                                 ret = LBS_CLIENT_ERROR_DBUS_CALL;
396                         }
397                         g_error_free(error);
398                         g_variant_unref(param);
399                         g_variant_unref(method);
400
401                         lbs_client_signal_unsubcribe(handle);
402                         return ret;
403                 }
404                 if (reg) {
405                         g_variant_unref(reg);
406                         reg = NULL;
407                 }
408
409                 g_object_unref(proxy);
410         }
411
412         /* g_variant_builder_unref(builder); */
413         g_variant_unref(method);
414         g_variant_unref(param);
415
416         lbs_client_privacy_signal_subcribe(handle);
417         handle->is_started = TRUE;
418
419         return LBS_CLIENT_ERROR_NONE;
420 }
421
422 EXPORT_API int
423 lbs_client_set_position_update_interval(lbs_client_dbus_h lbs_client, unsigned int interval)
424 {
425         LBS_CLIENT_LOGD("lbs_client_set_position_update_interval");
426         lbs_client_dbus_s *handle = (lbs_client_dbus_s *)lbs_client;
427
428         g_return_val_if_fail(handle, LBS_CLIENT_ERROR_PARAMETER);
429         g_return_val_if_fail(handle->is_started == TRUE, LBS_CLIENT_ERROR_STATUS);
430
431         GVariant *reg = NULL;
432         GVariant *param = NULL;
433         GVariant *method = NULL;
434         GError *error = NULL;
435         GVariantBuilder *builder = NULL;
436         GDBusProxy *proxy = NULL;
437         gchar *signal_path = NULL;
438
439         signal_path = g_strdup_printf("%s/%s", SERVICE_PATH, "SAMSUNG");
440         LBS_CLIENT_LOGD("LBS signal subscribe Object Path [%s]", signal_path);
441         g_free(signal_path);
442
443         LBS_CLIENT_LOGD("SET option INTERVAL_UPDATE:[%u], method:[%d]", interval, method);
444         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
445         g_variant_builder_add(builder, "{sv}", "CMD", g_variant_new_string("SET:OPT"));
446         g_variant_builder_add(builder, "{sv}", "INTERVAL_UPDATE", g_variant_new_uint32(interval));
447         g_variant_builder_add(builder, "{sv}", "METHOD", g_variant_new_int32(handle->method));
448         param = g_variant_ref_sink(g_variant_new("(@a{sv})", g_variant_builder_end(builder)));
449         method = g_variant_ref_sink(g_variant_new("(i)", handle->method));
450
451         proxy = g_dbus_proxy_new_sync(handle->conn, G_DBUS_PROXY_FLAGS_NONE, NULL, SERVICE_NAME, SERVICE_PATH, "org.tizen.lbs.Manager", NULL, &error);
452         if (proxy) {
453                 reg = g_dbus_proxy_call_sync(proxy, "SetOptions", param, G_DBUS_CALL_FLAGS_NO_AUTO_START, -1, NULL, &error);
454                 if (reg) {
455                         g_variant_unref(reg);
456                         reg = NULL;
457                 }
458
459                 g_object_unref(proxy);
460         }
461         /* g_variant_builder_unref(builder); */
462         g_variant_unref(param);
463         g_variant_unref(method);
464
465         return LBS_CLIENT_ERROR_NONE;
466 }
467
468 EXPORT_API int
469 lbs_client_batch_stop(lbs_client_dbus_h lbs_client)
470 {
471         LBS_CLIENT_LOGD("lbs_client_batch_stop");
472
473         lbs_client_dbus_s *handle = (lbs_client_dbus_s *)lbs_client;
474         g_return_val_if_fail(handle, LBS_CLIENT_ERROR_PARAMETER);
475         g_return_val_if_fail(handle->is_started == TRUE, LBS_CLIENT_ERROR_STATUS);
476
477         int ret = LBS_CLIENT_ERROR_NONE;
478         GVariant *param = NULL, *method = NULL, *reg = NULL;
479         GError *error = NULL;
480         GVariantBuilder *builder = NULL;
481
482         lbs_client_privacy_signal_unsubcribe(handle);
483         lbs_client_signal_unsubcribe(handle);
484
485         /* Stop */
486         LBS_CLIENT_LOGD("STOP: CMD-STOP_BATCH");
487         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
488         g_variant_builder_add(builder, "{sv}", "CMD", g_variant_new_string("STOP_BATCH"));
489
490         LBS_CLIENT_LOGD("METHOD: %d", handle->method);
491         g_variant_builder_add(builder, "{sv}", "METHOD", g_variant_new_int32(handle->method));
492         param = g_variant_ref_sink(g_variant_new("(@a{sv})", g_variant_builder_end(builder)));
493         method = g_variant_ref_sink(g_variant_new("(i)", handle->method));
494
495         GDBusProxy *proxy = NULL;
496         proxy = g_dbus_proxy_new_sync(handle->conn, G_DBUS_PROXY_FLAGS_NONE, NULL, SERVICE_NAME, SERVICE_PATH, "org.tizen.lbs.Manager", NULL, &error);
497
498         if (error && error->message) {
499                 if (error->code == G_DBUS_ERROR_ACCESS_DENIED) {
500                         LBS_CLIENT_LOGI("Access denied. Msg[%s]", error->message);
501                         ret = LBS_CLIENT_ERROR_ACCESS_DENIED;
502                 } else {
503                         LBS_CLIENT_LOGI("Fail to new proxy ErrCode[%d], Msg[%s]", error->code, error->message);
504                         ret = LBS_CLIENT_ERROR_DBUS_CALL;
505                 }
506                 g_error_free(error);
507                 g_variant_unref(param);
508                 g_variant_unref(method);
509
510                 g_object_unref(proxy);
511                 return ret;
512         }
513
514         error = NULL;
515         if (proxy) {
516                 reg = g_dbus_proxy_call_sync(proxy, "SetOptions", param, G_DBUS_CALL_FLAGS_NO_AUTO_START, -1, NULL, &error);
517                 if (error && error->message) {
518                         if (error->code == G_DBUS_ERROR_ACCESS_DENIED) {
519                                 LBS_CLIENT_LOGI("Access denied. Msg[%s]", error->message);
520                                 ret = LBS_CLIENT_ERROR_ACCESS_DENIED;
521                         } else {
522                                 LBS_CLIENT_LOGI("Fail to proxy call. ErrCode[%d], Msg[%s]", error->code, error->message);
523                                 ret = LBS_CLIENT_ERROR_DBUS_CALL;
524                         }
525                         g_error_free(error);
526                         g_variant_unref(param);
527                         g_variant_unref(method);
528
529                         g_object_unref(proxy);
530                         return ret;
531                 }
532
533                 if (reg) {
534                         g_variant_unref(reg);
535                         reg = NULL;
536                 }
537
538                 g_object_unref(proxy);
539         }
540         /* g_variant_builder_unref (builder); */
541         g_variant_unref(param);
542         g_variant_unref(method);
543
544         handle->is_started = FALSE;
545
546         return ret;
547 }
548
549 EXPORT_API int
550 lbs_client_start(lbs_client_dbus_h lbs_client, unsigned int interval, lbs_client_callback_e callback_type, lbs_client_cb callback, void *user_data)
551 {
552         LBS_CLIENT_LOGD("lbs_client_start");
553         g_return_val_if_fail(lbs_client, LBS_CLIENT_ERROR_PARAMETER);
554         g_return_val_if_fail(callback_type >= LBS_CLIENT_LOCATION_CB && callback_type <= LBS_CLIENT_BATCH_CB, LBS_CLIENT_ERROR_PARAMETER);
555
556         lbs_client_dbus_s *handle = (lbs_client_dbus_s *)lbs_client;
557         g_return_val_if_fail(handle->is_started == FALSE, LBS_CLIENT_ERROR_STATUS);
558
559         GVariant *reg = NULL;
560         GVariant *param = NULL, *method = NULL;
561         GError *error = NULL;
562         GVariantBuilder *builder = NULL;
563         GDBusProxy *proxy = NULL;
564         gchar *signal_path = NULL;
565         gchar *app_id = NULL;
566         int ret = LBS_CLIENT_ERROR_NONE;
567
568         signal_path = g_strdup_printf("%s/%s", SERVICE_PATH, "SAMSUNG");
569         LBS_CLIENT_SECLOG("LBS signal subscribe Object Path [%s]", signal_path);
570
571         if (callback) {
572                 handle->user_cb = callback;
573                 handle->user_data = user_data;
574
575                 if (callback_type & LBS_CLIENT_LOCATION_CB) {
576                         handle->loc_evt_id = g_dbus_connection_signal_subscribe(
577                                                                         handle->conn, SERVICE_NAME, "org.tizen.lbs.Position", "PositionChanged",
578                                                                         signal_path, NULL, G_DBUS_SIGNAL_FLAGS_NONE, __signal_callback, handle, NULL);
579
580                         if (handle->loc_evt_id)
581                                 LBS_CLIENT_LOGD("Listening Position info");
582                         else
583                                 LBS_CLIENT_LOGD("Fail to listen Position info");
584                 }
585
586                 if (callback_type & LBS_CLIENT_LOCATION_STATUS_CB) {
587                         handle->loc_status_evt_id = g_dbus_connection_signal_subscribe(handle->conn,
588                                                                                 SERVICE_NAME, "org.tizen.lbs.Manager", "StatusChanged", SERVICE_PATH,
589                                                                                 NULL, G_DBUS_SIGNAL_FLAGS_NONE, __signal_callback, handle, NULL);
590
591                         if (handle->loc_status_evt_id)
592                                 LBS_CLIENT_LOGD("Listening location Status");
593                         else
594                                 LBS_CLIENT_LOGD("Fail to listen location Status");
595                 }
596
597                 if (callback_type & LBS_CLIENT_SATELLITE_CB) {
598                         handle->sat_evt_id = g_dbus_connection_signal_subscribe(handle->conn,
599                                                                         SERVICE_NAME, "org.tizen.lbs.Satellite", "SatelliteChanged",
600                                                                         signal_path, NULL, G_DBUS_SIGNAL_FLAGS_NONE, __signal_callback, handle, NULL);
601
602                         if (handle->sat_evt_id)
603                                 LBS_CLIENT_LOGD("Listening satellite info");
604                         else
605                                 LBS_CLIENT_LOGD("Fail to listen satellite info");
606                 }
607
608                 if (callback_type & LBS_CLIENT_NMEA_CB) {
609                         handle->nmea_evt_id = g_dbus_connection_signal_subscribe(handle->conn,
610                                                                          SERVICE_NAME, "org.tizen.lbs.Nmea", "NmeaChanged",
611                                                                          signal_path, NULL, G_DBUS_SIGNAL_FLAGS_NONE, __signal_callback, handle, NULL);
612
613                         if (handle->nmea_evt_id)
614                                 LBS_CLIENT_LOGD("Listening nmea info");
615                         else
616                                 LBS_CLIENT_LOGD("Fail to listen nmea info");
617                 }
618         }
619         g_free(signal_path);
620
621         /* Start */
622         LBS_CLIENT_LOGD("START: CMD-START");
623         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
624         g_variant_builder_add(builder, "{sv}", "CMD", g_variant_new_string("START"));
625
626         g_variant_builder_add(builder, "{sv}", "METHOD", g_variant_new_int32(handle->method));
627         g_variant_builder_add(builder, "{sv}", "INTERVAL", g_variant_new_uint32(interval));
628
629         if (__lbs_get_appid(&app_id)) {
630                 LBS_CLIENT_LOGD("[%s] Request START", app_id);
631                 g_variant_builder_add(builder, "{sv}", "APP_ID", g_variant_new_string(app_id));
632
633                 if (app_id)
634                         g_free(app_id);
635         }
636
637         param = g_variant_ref_sink(g_variant_new("(@a{sv})", g_variant_builder_end(builder)));
638         method = g_variant_ref_sink(g_variant_new("(i)", handle->method));
639         proxy = g_dbus_proxy_new_sync(handle->conn,  /* GDBusConnection */
640                                                                   G_DBUS_PROXY_FLAGS_NONE, /* GDbusProxyFlags */
641                                                                   NULL, SERVICE_NAME, SERVICE_PATH, "org.tizen.lbs.Manager", NULL, &error);
642
643         if (error && error->message) {
644                 if (error->code == G_DBUS_ERROR_ACCESS_DENIED) {
645                         LBS_CLIENT_LOGI("Access denied. Msg[%s]", error->message);
646                         ret = LBS_CLIENT_ERROR_ACCESS_DENIED;
647                 } else {
648                         LBS_CLIENT_LOGI("Fail to new proxy ErrCode[%d], Msg[%s]", error->code, error->message);
649                         ret = LBS_CLIENT_ERROR_DBUS_CALL;
650                 }
651                 g_error_free(error);
652                 g_variant_unref(param);
653                 g_variant_unref(method);
654                 lbs_client_signal_unsubcribe(handle);
655                 return ret;
656         }
657
658         if (proxy) {
659                 reg = g_dbus_proxy_call_sync(proxy, "AddReference", method, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
660
661                 if (error && error->message) {
662                         if (error->code == G_DBUS_ERROR_ACCESS_DENIED) {
663                                 LBS_CLIENT_LOGI("Access denied. Msg[%s]", error->message);
664                                 ret = LBS_CLIENT_ERROR_ACCESS_DENIED;
665                         } else {
666                                 LBS_CLIENT_LOGI("Fail to new proxy ErrCode[%d], Msg[%s]", error->code, error->message);
667                                 ret = LBS_CLIENT_ERROR_DBUS_CALL;
668                         }
669                         g_error_free(error);
670                         g_variant_unref(param);
671                         g_variant_unref(method);
672                         lbs_client_signal_unsubcribe(handle);
673                         return ret;
674                 }
675                 if (reg) {
676                         g_variant_unref(reg);
677                         reg = NULL;
678                 }
679
680                 reg = g_dbus_proxy_call_sync(proxy, "SetOptions", param, G_DBUS_CALL_FLAGS_NO_AUTO_START, -1, NULL, &error);
681                 if (error && error->message) {
682                         if (error->code == G_DBUS_ERROR_ACCESS_DENIED) {
683                                 LBS_CLIENT_LOGI("Access denied. Msg[%s]", error->message);
684                                 ret = LBS_CLIENT_ERROR_ACCESS_DENIED;
685                         } else {
686                                 LBS_CLIENT_LOGI("Fail to new proxy ErrCode[%d], Msg[%s]", error->code, error->message);
687                                 ret = LBS_CLIENT_ERROR_DBUS_CALL;
688                         }
689                         g_error_free(error);
690                         g_variant_unref(param);
691                         g_variant_unref(method);
692
693                         lbs_client_signal_unsubcribe(handle);
694                         return ret;
695                 }
696                 if (reg) {
697                         g_variant_unref(reg);
698                         reg = NULL;
699                 }
700
701                 g_object_unref(proxy);
702         }
703
704         /* g_variant_builder_unref (builder); */
705         g_variant_unref(param);
706         g_variant_unref(method);
707
708         lbs_client_privacy_signal_subcribe(handle);
709         handle->is_started = TRUE;
710
711         return LBS_CLIENT_ERROR_NONE;
712 }
713
714 EXPORT_API int
715 lbs_client_stop(lbs_client_dbus_h lbs_client)
716 {
717         LBS_CLIENT_LOGD("lbs_client_stop");
718
719         lbs_client_dbus_s *handle = (lbs_client_dbus_s *)lbs_client;
720         g_return_val_if_fail(handle, LBS_CLIENT_ERROR_PARAMETER);
721         g_return_val_if_fail(handle->is_started == TRUE, LBS_CLIENT_ERROR_STATUS);
722
723         int ret = LBS_CLIENT_ERROR_NONE;
724         GVariant *param = NULL, *method = NULL, *reg = NULL;
725         GError *error = NULL;
726         GVariantBuilder *builder = NULL;
727         gchar *app_id = NULL;
728
729         lbs_client_privacy_signal_unsubcribe(handle);
730         lbs_client_signal_unsubcribe(handle);
731
732         /* Stop */
733         LBS_CLIENT_LOGD("STOP: CMD-STOP");
734         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
735         g_variant_builder_add(builder, "{sv}", "CMD", g_variant_new_string("STOP"));
736
737         LBS_CLIENT_LOGD("METHOD: %d", handle->method);
738         g_variant_builder_add(builder, "{sv}", "METHOD", g_variant_new_int32(handle->method));
739
740         if (__lbs_get_appid(&app_id)) {
741                 LBS_CLIENT_LOGD("[%s] Request STOP", app_id);
742                 g_variant_builder_add(builder, "{sv}", "APP_ID", g_variant_new_string(app_id));
743
744                 if (app_id)
745                         g_free(app_id);
746         }
747
748         param = g_variant_ref_sink(g_variant_new("(@a{sv})", g_variant_builder_end(builder)));
749         method = g_variant_ref_sink(g_variant_new("(i)", handle->method));
750
751         GDBusProxy *proxy = NULL;
752         proxy = g_dbus_proxy_new_sync(handle->conn,  /* GDBusConnection */
753                                                                   G_DBUS_PROXY_FLAGS_NONE, /*GDbusProxyFlags */
754                                                                   NULL, SERVICE_NAME, SERVICE_PATH, "org.tizen.lbs.Manager", NULL, &error);
755
756         if (error && error->message) {
757                 if (error->code == G_DBUS_ERROR_ACCESS_DENIED) {
758                         LBS_CLIENT_LOGI("Access denied. Msg[%s]", error->message);
759                         ret = LBS_CLIENT_ERROR_ACCESS_DENIED;
760                 } else {
761                         LBS_CLIENT_LOGI("Fail to new proxy ErrCode[%d], Msg[%s]", error->code, error->message);
762                         ret = LBS_CLIENT_ERROR_DBUS_CALL;
763                 }
764                 g_error_free(error);
765                 g_variant_unref(param);
766                 g_variant_unref(method);
767
768                 g_object_unref(proxy);
769                 return ret;
770         }
771
772         error = NULL;
773         if (proxy) {
774                 reg = g_dbus_proxy_call_sync(proxy, "SetOptions", param, G_DBUS_CALL_FLAGS_NO_AUTO_START, -1, NULL, &error);
775                 if (error && error->message) {
776                         if (error->code == G_DBUS_ERROR_ACCESS_DENIED) {
777                                 LBS_CLIENT_LOGI("Access denied. Msg[%s]", error->message);
778                                 ret = LBS_CLIENT_ERROR_ACCESS_DENIED;
779                         } else {
780                                 LBS_CLIENT_LOGI("Fail to proxy call. ErrCode[%d], Msg[%s]", error->code, error->message);
781                                 ret = LBS_CLIENT_ERROR_DBUS_CALL;
782                         }
783                         g_error_free(error);
784                         g_variant_unref(param);
785                         g_variant_unref(method);
786
787                         g_object_unref(proxy);
788                         return ret;
789                 }
790
791                 if (reg) {
792                         g_variant_unref(reg);
793                         reg = NULL;
794                 }
795
796                 reg = g_dbus_proxy_call_sync(proxy, "RemoveReference", method, G_DBUS_CALL_FLAGS_NO_AUTO_START, -1, NULL, &error);
797
798                 if (error && error->message) {
799                         if (error->code == G_DBUS_ERROR_ACCESS_DENIED) {
800                                 LBS_CLIENT_LOGI("Access denied. Msg[%s]", error->message);
801                                 ret = LBS_CLIENT_ERROR_ACCESS_DENIED;
802                         } else {
803                                 LBS_CLIENT_LOGI("Fail to proxy call. ErrCode[%d], Msg[%s]", error->code, error->message);
804                                 ret = LBS_CLIENT_ERROR_DBUS_CALL;
805                         }
806                         g_error_free(error);
807                         g_variant_unref(param);
808                         g_variant_unref(method);
809
810                         g_object_unref(proxy);
811                         return ret;
812                 }
813                 if (reg) {
814                         g_variant_unref(reg);
815                         reg = NULL;
816                 }
817
818                 g_object_unref(proxy);
819         }
820         /* g_variant_builder_unref (builder); */
821         g_variant_unref(param);
822         g_variant_unref(method);
823
824         handle->is_started = FALSE;
825
826         return ret;
827 }
828
829 EXPORT_API int
830 lbs_client_get_nmea(lbs_client_dbus_h lbs_client, int *timestamp, char **nmea)
831 {
832         g_return_val_if_fail(lbs_client, LBS_CLIENT_ERROR_PARAMETER);
833         g_return_val_if_fail(timestamp, LBS_CLIENT_ERROR_PARAMETER);
834         g_return_val_if_fail(nmea, LBS_CLIENT_ERROR_PARAMETER);
835
836         GError *error = NULL;
837         int ret = LBS_CLIENT_ERROR_NONE;
838
839         lbs_client_dbus_s *handle = (lbs_client_dbus_s *)lbs_client;
840         *timestamp = 0;
841         *nmea = NULL;
842
843         LbsNmea *proxy = NULL;
844         proxy = lbs_nmea_proxy_new_sync(handle->conn,
845                                                                         G_DBUS_PROXY_FLAGS_NONE,
846                                                                         SERVICE_NAME,
847                                                                         SERVICE_PATH,
848                                                                         NULL,
849                                                                         &error);
850
851         gint cur_timestamp = 0;
852         gchar *cur_nmea_data = NULL;
853
854         if (proxy) {
855                 ret = lbs_nmea_call_get_nmea_sync(proxy, &cur_timestamp, &cur_nmea_data, NULL, &error);
856                 if (error && error->message) {
857                         if (error->code == G_DBUS_ERROR_ACCESS_DENIED) {
858                                 LBS_CLIENT_LOGE("Access denied. Msg[%s]", error->message);
859                                 ret = LBS_CLIENT_ERROR_ACCESS_DENIED;
860                         } else {
861                                 LBS_CLIENT_LOGE("Fail to new proxy ErrCode[%d], Msg[%s]", error->code, error->message);
862                                 ret = LBS_CLIENT_ERROR_DBUS_CALL;
863                         }
864                         g_error_free(error);
865                         return ret;
866                 }
867
868                 LBS_CLIENT_LOGD("Get NMEA: Timestamp[%d], NMEA[%s]", cur_timestamp, cur_nmea_data);
869                 *timestamp = cur_timestamp;
870                 *nmea = cur_nmea_data;
871
872                 g_object_unref(proxy);
873         }
874
875         return LBS_CLIENT_ERROR_NONE;
876 }
877
878 static int
879 _client_create_connection(lbs_client_dbus_s *client)
880 {
881         LBS_CLIENT_LOGD("create connection");
882         g_return_val_if_fail(client, LBS_CLIENT_ERROR_PARAMETER);
883         GError *error = NULL;
884
885         client->conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
886         if (!client->conn) {
887                 if (error && error->message) {
888                         LBS_CLIENT_LOGI("Fail to get GBus. ErrCode[%d], Msg[%s]", error->code, error->message);
889                         g_error_free(error);
890                         error = NULL;
891                 }
892                 LBS_CLIENT_LOGI("Fail to get addr of bus.");
893                 return LBS_CLIENT_ERROR_CONNECTION;
894         }
895
896         LBS_CLIENT_LOGD("client->conn: %p", client->conn);
897
898         return LBS_CLIENT_ERROR_NONE;
899 }
900
901 static void _glib_log(const gchar *log_domain, GLogLevelFlags log_level,
902                                           const gchar *msg, gpointer user_data)
903 {
904         LBS_CLIENT_LOGD("GLIB[%d] : %s", log_level, msg);
905 }
906
907 /* The reason why we seperate this from start is to support IPC for db operation between a server and a client. */
908 EXPORT_API int
909 lbs_client_create(lbs_client_method_e method, lbs_client_dbus_h *lbs_client)
910 {
911         LBS_CLIENT_LOGD("lbs_client_create");
912         g_return_val_if_fail(lbs_client, LBS_CLIENT_ERROR_PARAMETER);
913
914         int ret = LBS_CLIENT_ERROR_NONE;
915
916         lbs_client_dbus_s *client = g_new0(lbs_client_dbus_s, 1);
917         g_return_val_if_fail(client, LBS_CLIENT_ERROR_MEMORY);
918
919         g_log_set_default_handler(_glib_log, NULL);
920
921         ret = _client_create_connection(client);
922         if (ret != LBS_CLIENT_ERROR_NONE) {
923                 g_free(client);
924                 return ret;
925         }
926
927         client->method = method;
928
929         *lbs_client = (lbs_client_dbus_s *)client;
930
931         return LBS_CLIENT_ERROR_NONE;
932 }
933
934 EXPORT_API int
935 lbs_client_destroy(lbs_client_dbus_h lbs_client)
936 {
937         LBS_CLIENT_LOGD("lbs_client_destroy");
938         g_return_val_if_fail(lbs_client, LBS_CLIENT_ERROR_PARAMETER);
939
940         lbs_client_dbus_s *handle = (lbs_client_dbus_s *)lbs_client;
941         g_return_val_if_fail(handle->is_started == FALSE, LBS_CLIENT_ERROR_STATUS);
942
943         handle->user_cb = NULL;
944         handle->batch_cb = NULL;
945         handle->set_mock_cb = NULL;
946         handle->user_data = NULL;
947
948         if (handle->conn) {
949                 g_object_unref(handle->conn);
950                 handle->conn = NULL;
951         }
952
953         g_free(handle);
954
955         return LBS_CLIENT_ERROR_NONE;
956 }
957
958 /* Tizen 3.0 */
959
960 static void __dbus_set_location_callback(GObject *source_object, GAsyncResult *res, gpointer user_data)
961 {
962         LBS_CLIENT_LOGD("ENTER >>> __dbus_set_location_callback");
963
964         g_return_if_fail(source_object);
965         g_return_if_fail(res);
966
967         lbs_client_dbus_s *handle = (lbs_client_dbus_s *)user_data;
968         GError *error = NULL;
969         gboolean success = FALSE;
970         gchar *sig = NULL;
971         GVariant *param = NULL;
972
973         LbsManager *proxy = (LbsManager *)source_object;
974
975         /* TODO: lbs-server will send method and status via DBUS. Have to change lbs.xml */
976         success = lbs_manager_call_set_mock_location_finish(proxy, res, &error);
977         if (success) {
978                 if (handle && handle->set_mock_cb) {
979                         sig = g_strdup("SetLocation");
980                         param = g_variant_new("(ii)", LBS_CLIENT_METHOD_MOCK, 5); /* LBS_STATUS_BATCH + 1 */
981                         handle->set_mock_cb(sig, param, handle->user_data);
982
983                         g_free(sig);
984                         g_variant_unref(param);
985                 }
986         } else {
987                 LBS_CLIENT_LOGW("SetLocation failed!!!");
988                 if (handle && handle->set_mock_cb) {
989                         sig = g_strdup("SetLocation");
990                         param = g_variant_new("(ii)", LBS_CLIENT_METHOD_MOCK, 6); /* LBS_STATUS_BATCH + 2 */
991                         handle->set_mock_cb(sig, param, handle->user_data);
992
993                         g_free(sig);
994                         g_variant_unref(param);
995                 }
996
997                 if (error && error->message) {
998                         if (error->code == G_DBUS_ERROR_ACCESS_DENIED)
999                                 LBS_CLIENT_LOGE("Access denied. Msg[%s]", error->message);
1000                         else
1001                                 LBS_CLIENT_LOGE("Fail to new proxy ErrCode[%d], Msg[%s]", error->code, error->message);
1002
1003                         g_error_free(error);
1004                 }
1005         }
1006
1007         LBS_CLIENT_LOGD("EXIT <<<");
1008 }
1009
1010 EXPORT_API int
1011 lbs_client_set_mock_location_async(lbs_client_dbus_h lbs_client,
1012         gint method,
1013         gdouble latitude,
1014         gdouble longitude,
1015         gdouble altitude,
1016         gdouble speed,
1017         gdouble direction,
1018         gdouble accuracy,
1019         lbs_client_cb callback, void *user_data)
1020 {
1021         LBS_CLIENT_LOGD("ENTER >>> lbs_client_set_mock_location_async");
1022         g_return_val_if_fail(lbs_client, LBS_CLIENT_ERROR_PARAMETER);
1023
1024         lbs_client_dbus_s *handle = (lbs_client_dbus_s *)lbs_client;
1025         int ret = LBS_CLIENT_ERROR_NONE;
1026
1027         handle->set_mock_cb = callback;
1028         handle->user_data = user_data;
1029
1030         LbsManager *proxy = NULL;
1031         GError *error = NULL;
1032
1033         proxy = lbs_manager_proxy_new_sync(handle->conn, G_DBUS_PROXY_FLAGS_NONE,
1034                                                                         SERVICE_NAME, SERVICE_PATH, NULL, &error);
1035
1036         if (proxy) {
1037                 lbs_manager_call_set_mock_location(proxy, method, latitude, longitude, altitude, speed, direction,
1038                                                                                         accuracy, NULL, __dbus_set_location_callback, handle);
1039
1040                 g_object_unref(proxy);
1041                 proxy = NULL;
1042         } else {
1043                 if (error && error->message) {
1044                         if (error->code == G_DBUS_ERROR_ACCESS_DENIED) {
1045                                 LBS_CLIENT_LOGE("Access denied. Msg[%s]", error->message);
1046                                 ret = LBS_CLIENT_ERROR_ACCESS_DENIED;
1047                         } else {
1048                                 LBS_CLIENT_LOGE("Fail to new proxy ErrCode[%d], Msg[%s]", error->code, error->message);
1049                                 ret = LBS_CLIENT_ERROR_DBUS_CALL;
1050                         }
1051                         g_error_free(error);
1052                 }
1053         }
1054         LBS_CLIENT_LOGD("EXIT <<<");
1055
1056         return ret;
1057 }