Dynamic interval table for multi handle
[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         unsigned int interval;
45         lbs_client_cb user_cb;
46         lbs_client_cb batch_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, handle->interval) != 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, unsigned int prev_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 -> %u], method:[%d]", prev_interval, 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}", "PREV_INTERVAL", g_variant_new_uint32(prev_interval));
448         g_variant_builder_add(builder, "{sv}", "METHOD", g_variant_new_int32(handle->method));
449         param = g_variant_ref_sink(g_variant_new("(@a{sv})", g_variant_builder_end(builder)));
450         method = g_variant_ref_sink(g_variant_new("(i)", handle->method));
451
452         proxy = g_dbus_proxy_new_sync(handle->conn, G_DBUS_PROXY_FLAGS_NONE, NULL, SERVICE_NAME, SERVICE_PATH, "org.tizen.lbs.Manager", NULL, &error);
453         if (proxy) {
454                 reg = g_dbus_proxy_call_sync(proxy, "SetOptions", param, G_DBUS_CALL_FLAGS_NO_AUTO_START, -1, NULL, &error);
455                 if (reg) {
456                         g_variant_unref(reg);
457                         reg = NULL;
458                 }
459
460                 g_object_unref(proxy);
461         }
462         /* g_variant_builder_unref(builder); */
463         g_variant_unref(param);
464         g_variant_unref(method);
465
466         return LBS_CLIENT_ERROR_NONE;
467 }
468
469 EXPORT_API int
470 lbs_client_batch_stop(lbs_client_dbus_h lbs_client)
471 {
472         LBS_CLIENT_LOGD("lbs_client_batch_stop");
473
474         lbs_client_dbus_s *handle = (lbs_client_dbus_s *)lbs_client;
475         g_return_val_if_fail(handle, LBS_CLIENT_ERROR_PARAMETER);
476         g_return_val_if_fail(handle->is_started == TRUE, LBS_CLIENT_ERROR_STATUS);
477
478         int ret = LBS_CLIENT_ERROR_NONE;
479         GVariant *param = NULL, *method = NULL, *reg = NULL;
480         GError *error = NULL;
481         GVariantBuilder *builder = NULL;
482
483         lbs_client_privacy_signal_unsubcribe(handle);
484         lbs_client_signal_unsubcribe(handle);
485
486         /* Stop */
487         LBS_CLIENT_LOGD("STOP: CMD-STOP_BATCH");
488         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
489         g_variant_builder_add(builder, "{sv}", "CMD", g_variant_new_string("STOP_BATCH"));
490
491         LBS_CLIENT_LOGD("METHOD: %d", handle->method);
492         g_variant_builder_add(builder, "{sv}", "METHOD", g_variant_new_int32(handle->method));
493         param = g_variant_ref_sink(g_variant_new("(@a{sv})", g_variant_builder_end(builder)));
494         method = g_variant_ref_sink(g_variant_new("(i)", handle->method));
495
496         GDBusProxy *proxy = NULL;
497         proxy = g_dbus_proxy_new_sync(handle->conn, G_DBUS_PROXY_FLAGS_NONE, NULL, SERVICE_NAME, SERVICE_PATH, "org.tizen.lbs.Manager", NULL, &error);
498
499         if (error && error->message) {
500                 if (error->code == G_DBUS_ERROR_ACCESS_DENIED) {
501                         LBS_CLIENT_LOGI("Access denied. Msg[%s]", error->message);
502                         ret = LBS_CLIENT_ERROR_ACCESS_DENIED;
503                 } else {
504                         LBS_CLIENT_LOGI("Fail to new proxy ErrCode[%d], Msg[%s]", error->code, error->message);
505                         ret = LBS_CLIENT_ERROR_DBUS_CALL;
506                 }
507                 g_error_free(error);
508                 g_variant_unref(param);
509                 g_variant_unref(method);
510
511                 g_object_unref(proxy);
512                 return ret;
513         }
514
515         error = NULL;
516         if (proxy) {
517                 reg = g_dbus_proxy_call_sync(proxy, "SetOptions", param, G_DBUS_CALL_FLAGS_NO_AUTO_START, -1, NULL, &error);
518                 if (error && error->message) {
519                         if (error->code == G_DBUS_ERROR_ACCESS_DENIED) {
520                                 LBS_CLIENT_LOGI("Access denied. Msg[%s]", error->message);
521                                 ret = LBS_CLIENT_ERROR_ACCESS_DENIED;
522                         } else {
523                                 LBS_CLIENT_LOGI("Fail to proxy call. ErrCode[%d], Msg[%s]", error->code, error->message);
524                                 ret = LBS_CLIENT_ERROR_DBUS_CALL;
525                         }
526                         g_error_free(error);
527                         g_variant_unref(param);
528                         g_variant_unref(method);
529
530                         g_object_unref(proxy);
531                         return ret;
532                 }
533
534                 if (reg) {
535                         g_variant_unref(reg);
536                         reg = NULL;
537                 }
538
539                 g_object_unref(proxy);
540         }
541         /* g_variant_builder_unref (builder); */
542         g_variant_unref(param);
543         g_variant_unref(method);
544
545         handle->is_started = FALSE;
546
547         return ret;
548 }
549
550 EXPORT_API int
551 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)
552 {
553         LBS_CLIENT_LOGD("lbs_client_start");
554         g_return_val_if_fail(lbs_client, LBS_CLIENT_ERROR_PARAMETER);
555         g_return_val_if_fail(callback_type >= LBS_CLIENT_LOCATION_CB && callback_type <= LBS_CLIENT_BATCH_CB, LBS_CLIENT_ERROR_PARAMETER);
556
557         lbs_client_dbus_s *handle = (lbs_client_dbus_s *)lbs_client;
558         g_return_val_if_fail(handle->is_started == FALSE, LBS_CLIENT_ERROR_STATUS);
559
560         GVariant *reg = NULL;
561         GVariant *param = NULL, *method = NULL;
562         GError *error = NULL;
563         GVariantBuilder *builder = NULL;
564         GDBusProxy *proxy = NULL;
565         gchar *signal_path = NULL;
566         gchar *app_id = NULL;
567         int ret = LBS_CLIENT_ERROR_NONE;
568
569         signal_path = g_strdup_printf("%s/%s", SERVICE_PATH, "SAMSUNG");
570         LBS_CLIENT_SECLOG("LBS signal subscribe Object Path [%s]", signal_path);
571
572         if (callback) {
573                 handle->user_cb = callback;
574                 handle->user_data = user_data;
575
576                 if (callback_type & LBS_CLIENT_LOCATION_CB) {
577                         handle->loc_evt_id = g_dbus_connection_signal_subscribe(
578                                                                         handle->conn, SERVICE_NAME, "org.tizen.lbs.Position", "PositionChanged",
579                                                                         signal_path, NULL, G_DBUS_SIGNAL_FLAGS_NONE, __signal_callback, handle, NULL);
580
581                         if (handle->loc_evt_id)
582                                 LBS_CLIENT_LOGD("Listening Position info");
583                         else
584                                 LBS_CLIENT_LOGD("Fail to listen Position info");
585                 }
586
587                 if (callback_type & LBS_CLIENT_LOCATION_STATUS_CB) {
588                         handle->loc_status_evt_id = g_dbus_connection_signal_subscribe(handle->conn,
589                                                                                 SERVICE_NAME, "org.tizen.lbs.Manager", "StatusChanged", SERVICE_PATH,
590                                                                                 NULL, G_DBUS_SIGNAL_FLAGS_NONE, __signal_callback, handle, NULL);
591
592                         if (handle->loc_status_evt_id)
593                                 LBS_CLIENT_LOGD("Listening location Status");
594                         else
595                                 LBS_CLIENT_LOGD("Fail to listen location Status");
596                 }
597
598                 if (callback_type & LBS_CLIENT_SATELLITE_CB) {
599                         handle->sat_evt_id = g_dbus_connection_signal_subscribe(handle->conn,
600                                                                         SERVICE_NAME, "org.tizen.lbs.Satellite", "SatelliteChanged",
601                                                                         signal_path, NULL, G_DBUS_SIGNAL_FLAGS_NONE, __signal_callback, handle, NULL);
602
603                         if (handle->sat_evt_id)
604                                 LBS_CLIENT_LOGD("Listening satellite info");
605                         else
606                                 LBS_CLIENT_LOGD("Fail to listen satellite info");
607                 }
608
609                 if (callback_type & LBS_CLIENT_NMEA_CB) {
610                         handle->nmea_evt_id = g_dbus_connection_signal_subscribe(handle->conn,
611                                                                          SERVICE_NAME, "org.tizen.lbs.Nmea", "NmeaChanged",
612                                                                          signal_path, NULL, G_DBUS_SIGNAL_FLAGS_NONE, __signal_callback, handle, NULL);
613
614                         if (handle->nmea_evt_id)
615                                 LBS_CLIENT_LOGD("Listening nmea info");
616                         else
617                                 LBS_CLIENT_LOGD("Fail to listen nmea info");
618                 }
619         }
620         g_free(signal_path);
621
622         /* Start */
623         LBS_CLIENT_LOGD("START: CMD-START");
624         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
625         g_variant_builder_add(builder, "{sv}", "CMD", g_variant_new_string("START"));
626
627         g_variant_builder_add(builder, "{sv}", "METHOD", g_variant_new_int32(handle->method));
628         g_variant_builder_add(builder, "{sv}", "INTERVAL", g_variant_new_uint32(interval));
629
630         if (__lbs_get_appid(&app_id)) {
631                 LBS_CLIENT_LOGD("[%s] Request START", app_id);
632                 g_variant_builder_add(builder, "{sv}", "APP_ID", g_variant_new_string(app_id));
633
634                 if (app_id)
635                         g_free(app_id);
636         }
637
638         param = g_variant_ref_sink(g_variant_new("(@a{sv})", g_variant_builder_end(builder)));
639         method = g_variant_ref_sink(g_variant_new("(i)", handle->method));
640         proxy = g_dbus_proxy_new_sync(handle->conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
641                                                                         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         handle->interval = interval;
711
712         return LBS_CLIENT_ERROR_NONE;
713 }
714
715 EXPORT_API int
716 lbs_client_stop(lbs_client_dbus_h lbs_client, unsigned int interval)
717 {
718         LBS_CLIENT_LOGD("lbs_client_stop [interval: %d]", interval);
719
720         lbs_client_dbus_s *handle = (lbs_client_dbus_s *)lbs_client;
721         g_return_val_if_fail(handle, LBS_CLIENT_ERROR_PARAMETER);
722         g_return_val_if_fail(handle->is_started == TRUE, LBS_CLIENT_ERROR_STATUS);
723
724         int ret = LBS_CLIENT_ERROR_NONE;
725         GVariant *param = NULL, *method = NULL, *reg = NULL;
726         GError *error = NULL;
727         GVariantBuilder *builder = NULL;
728         gchar *app_id = NULL;
729
730         lbs_client_privacy_signal_unsubcribe(handle);
731         lbs_client_signal_unsubcribe(handle);
732
733         /* Stop */
734         LBS_CLIENT_LOGD("STOP: CMD-STOP");
735         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
736         g_variant_builder_add(builder, "{sv}", "CMD", g_variant_new_string("STOP"));
737
738         LBS_CLIENT_LOGD("METHOD: %d", handle->method);
739         g_variant_builder_add(builder, "{sv}", "METHOD", g_variant_new_int32(handle->method));
740         g_variant_builder_add(builder, "{sv}", "INTERVAL", g_variant_new_uint32(interval));
741
742         if (__lbs_get_appid(&app_id)) {
743                 LBS_CLIENT_LOGD("[%s] Request STOP", app_id);
744                 g_variant_builder_add(builder, "{sv}", "APP_ID", g_variant_new_string(app_id));
745
746                 if (app_id)
747                         g_free(app_id);
748         }
749
750         param = g_variant_ref_sink(g_variant_new("(@a{sv})", g_variant_builder_end(builder)));
751         method = g_variant_ref_sink(g_variant_new("(i)", handle->method));
752
753         GDBusProxy *proxy = NULL;
754         proxy = g_dbus_proxy_new_sync(handle->conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
755                                                                 SERVICE_NAME, SERVICE_PATH, "org.tizen.lbs.Manager", NULL, &error);
756
757         if (error && error->message) {
758                 if (error->code == G_DBUS_ERROR_ACCESS_DENIED) {
759                         LBS_CLIENT_LOGI("Access denied. Msg[%s]", error->message);
760                         ret = LBS_CLIENT_ERROR_ACCESS_DENIED;
761                 } else {
762                         LBS_CLIENT_LOGI("Fail to new proxy ErrCode[%d], Msg[%s]", error->code, error->message);
763                         ret = LBS_CLIENT_ERROR_DBUS_CALL;
764                 }
765                 g_error_free(error);
766                 g_variant_unref(param);
767                 g_variant_unref(method);
768
769                 g_object_unref(proxy);
770                 return ret;
771         }
772
773         error = NULL;
774         if (proxy) {
775                 reg = g_dbus_proxy_call_sync(proxy, "SetOptions", param, G_DBUS_CALL_FLAGS_NO_AUTO_START, -1, NULL, &error);
776                 if (error && error->message) {
777                         if (error->code == G_DBUS_ERROR_ACCESS_DENIED) {
778                                 LBS_CLIENT_LOGI("Access denied. Msg[%s]", error->message);
779                                 ret = LBS_CLIENT_ERROR_ACCESS_DENIED;
780                         } else {
781                                 LBS_CLIENT_LOGI("Fail to proxy call. ErrCode[%d], Msg[%s]", error->code, error->message);
782                                 ret = LBS_CLIENT_ERROR_DBUS_CALL;
783                         }
784                         g_error_free(error);
785                         g_variant_unref(param);
786                         g_variant_unref(method);
787
788                         g_object_unref(proxy);
789                         return ret;
790                 }
791
792                 if (reg) {
793                         g_variant_unref(reg);
794                         reg = NULL;
795                 }
796
797                 reg = g_dbus_proxy_call_sync(proxy, "RemoveReference", method, G_DBUS_CALL_FLAGS_NO_AUTO_START, -1, NULL, &error);
798
799                 if (error && error->message) {
800                         if (error->code == G_DBUS_ERROR_ACCESS_DENIED) {
801                                 LBS_CLIENT_LOGI("Access denied. Msg[%s]", error->message);
802                                 ret = LBS_CLIENT_ERROR_ACCESS_DENIED;
803                         } else {
804                                 LBS_CLIENT_LOGI("Fail to proxy call. ErrCode[%d], Msg[%s]", error->code, error->message);
805                                 ret = LBS_CLIENT_ERROR_DBUS_CALL;
806                         }
807                         g_error_free(error);
808                         g_variant_unref(param);
809                         g_variant_unref(method);
810
811                         g_object_unref(proxy);
812                         return ret;
813                 }
814                 if (reg) {
815                         g_variant_unref(reg);
816                         reg = NULL;
817                 }
818
819                 g_object_unref(proxy);
820         }
821         /* g_variant_builder_unref (builder); */
822         g_variant_unref(param);
823         g_variant_unref(method);
824
825         handle->is_started = FALSE;
826
827         return ret;
828 }
829
830 EXPORT_API int
831 lbs_client_get_nmea(lbs_client_dbus_h lbs_client, int *timestamp, char **nmea)
832 {
833         g_return_val_if_fail(lbs_client, LBS_CLIENT_ERROR_PARAMETER);
834         g_return_val_if_fail(timestamp, LBS_CLIENT_ERROR_PARAMETER);
835         g_return_val_if_fail(nmea, LBS_CLIENT_ERROR_PARAMETER);
836
837         GError *error = NULL;
838         int ret = LBS_CLIENT_ERROR_NONE;
839
840         lbs_client_dbus_s *handle = (lbs_client_dbus_s *)lbs_client;
841         *timestamp = 0;
842         *nmea = NULL;
843
844         LbsNmea *proxy = NULL;
845         proxy = lbs_nmea_proxy_new_sync(handle->conn,
846                                                                         G_DBUS_PROXY_FLAGS_NONE,
847                                                                         SERVICE_NAME,
848                                                                         SERVICE_PATH,
849                                                                         NULL,
850                                                                         &error);
851
852         gint cur_timestamp = 0;
853         gchar *cur_nmea_data = NULL;
854
855         if (proxy) {
856                 ret = lbs_nmea_call_get_nmea_sync(proxy, &cur_timestamp, &cur_nmea_data, NULL, &error);
857                 if (error && error->message) {
858                         if (error->code == G_DBUS_ERROR_ACCESS_DENIED) {
859                                 LBS_CLIENT_LOGE("Access denied. Msg[%s]", error->message);
860                                 ret = LBS_CLIENT_ERROR_ACCESS_DENIED;
861                         } else {
862                                 LBS_CLIENT_LOGE("Fail to new proxy ErrCode[%d], Msg[%s]", error->code, error->message);
863                                 ret = LBS_CLIENT_ERROR_DBUS_CALL;
864                         }
865                         g_error_free(error);
866                         return ret;
867                 }
868
869                 LBS_CLIENT_LOGD("Get NMEA: Timestamp[%d], NMEA[%s]", cur_timestamp, cur_nmea_data);
870                 *timestamp = cur_timestamp;
871                 *nmea = cur_nmea_data;
872
873                 g_object_unref(proxy);
874         }
875
876         return LBS_CLIENT_ERROR_NONE;
877 }
878
879 static int
880 _client_create_connection(lbs_client_dbus_s *client)
881 {
882         LBS_CLIENT_LOGD("create connection");
883         g_return_val_if_fail(client, LBS_CLIENT_ERROR_PARAMETER);
884         GError *error = NULL;
885
886         client->conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
887         if (!client->conn) {
888                 if (error && error->message) {
889                         LBS_CLIENT_LOGI("Fail to get GBus. ErrCode[%d], Msg[%s]", error->code, error->message);
890                         g_error_free(error);
891                         error = NULL;
892                 }
893                 LBS_CLIENT_LOGI("Fail to get addr of bus.");
894                 return LBS_CLIENT_ERROR_CONNECTION;
895         }
896
897         LBS_CLIENT_LOGD("client->conn: %p", client->conn);
898
899         return LBS_CLIENT_ERROR_NONE;
900 }
901
902 static void _glib_log(const gchar *log_domain, GLogLevelFlags log_level,
903                                           const gchar *msg, gpointer user_data)
904 {
905         LBS_CLIENT_LOGD("GLIB[%d] : %s", log_level, msg);
906 }
907
908 /* The reason why we seperate this from start is to support IPC for db operation between a server and a client. */
909 EXPORT_API int
910 lbs_client_create(lbs_client_method_e method, lbs_client_dbus_h *lbs_client)
911 {
912         LBS_CLIENT_LOGD("lbs_client_create");
913         g_return_val_if_fail(lbs_client, LBS_CLIENT_ERROR_PARAMETER);
914
915         int ret = LBS_CLIENT_ERROR_NONE;
916
917         lbs_client_dbus_s *client = g_new0(lbs_client_dbus_s, 1);
918         g_return_val_if_fail(client, LBS_CLIENT_ERROR_MEMORY);
919
920         g_log_set_default_handler(_glib_log, NULL);
921
922         ret = _client_create_connection(client);
923         if (ret != LBS_CLIENT_ERROR_NONE) {
924                 g_free(client);
925                 return ret;
926         }
927
928         client->method = method;
929
930         *lbs_client = (lbs_client_dbus_s *)client;
931
932         return LBS_CLIENT_ERROR_NONE;
933 }
934
935 EXPORT_API int
936 lbs_client_destroy(lbs_client_dbus_h lbs_client)
937 {
938         LBS_CLIENT_LOGD("lbs_client_destroy");
939         g_return_val_if_fail(lbs_client, LBS_CLIENT_ERROR_PARAMETER);
940
941         lbs_client_dbus_s *handle = (lbs_client_dbus_s *)lbs_client;
942         g_return_val_if_fail(handle->is_started == FALSE, LBS_CLIENT_ERROR_STATUS);
943
944         handle->user_cb = NULL;
945         handle->batch_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(">>> __dbus_set_location_callback");
963
964         g_return_if_fail(source_object);
965         g_return_if_fail(res);
966
967         GError *error = NULL;
968         gboolean success = FALSE;
969         LbsManager *proxy = (LbsManager *)source_object;
970
971         /* TODO: lbs-server will send method and status via DBUS. Have to change lbs.xml */
972         success = lbs_manager_call_set_mock_location_finish(proxy, res, &error);
973         if (success != TRUE) {
974                 LBS_CLIENT_LOGW("SetLocation failed!!!");
975
976                 if (error && error->message) {
977                         if (error->code == G_DBUS_ERROR_ACCESS_DENIED)
978                                 LBS_CLIENT_LOGE("Access denied. Msg[%s]", error->message);
979                         else
980                                 LBS_CLIENT_LOGE("Fail to new proxy ErrCode[%d], Msg[%s]", error->code, error->message);
981
982                         g_error_free(error);
983                 }
984         }
985 }
986
987 EXPORT_API int
988 lbs_client_set_mock_location_async(lbs_client_dbus_h lbs_client, gint method,
989         gdouble latitude, gdouble longitude, gdouble altitude, gdouble speed, gdouble direction,
990         gdouble accuracy, lbs_client_cb callback, void *user_data)
991 {
992         LBS_CLIENT_LOGD("ENTER >>> lbs_client_set_mock_location_async");
993         g_return_val_if_fail(lbs_client, LBS_CLIENT_ERROR_PARAMETER);
994
995         lbs_client_dbus_s *handle = (lbs_client_dbus_s *)lbs_client;
996         int ret = LBS_CLIENT_ERROR_NONE;
997
998         handle->user_data = user_data;
999
1000         LbsManager *proxy = NULL;
1001         GError *error = NULL;
1002
1003         proxy = lbs_manager_proxy_new_sync(handle->conn, G_DBUS_PROXY_FLAGS_NONE, SERVICE_NAME, SERVICE_PATH, NULL, &error);
1004
1005         if (proxy) {
1006                 lbs_manager_call_set_mock_location(proxy, method, latitude, longitude, altitude, speed, direction,
1007                                                                                         accuracy, NULL, __dbus_set_location_callback, handle);
1008
1009                 g_object_unref(proxy);
1010                 proxy = NULL;
1011         } else {
1012                 if (error && error->message) {
1013                         if (error->code == G_DBUS_ERROR_ACCESS_DENIED) {
1014                                 LBS_CLIENT_LOGE("Access denied. Msg[%s]", error->message);
1015                                 ret = LBS_CLIENT_ERROR_ACCESS_DENIED;
1016                         } else {
1017                                 LBS_CLIENT_LOGE("Fail to new proxy ErrCode[%d], Msg[%s]", error->code, error->message);
1018                                 ret = LBS_CLIENT_ERROR_DBUS_CALL;
1019                         }
1020                         g_error_free(error);
1021                 }
1022         }
1023
1024         return ret;
1025 }
1026