1. Change tag style for error log
[platform/core/location/lbs-location.git] / location / manager / location-wps.c
1 /*
2  * libslp-location
3  *
4  * Copyright (c) 2010-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>
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 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include "location-setting.h"
27 #include "location-log.h"
28
29 #include "module-internal.h"
30
31 #include "location-wps.h"
32 #include "location-marshal.h"
33 #include "location-ielement.h"
34 #include "location-signaling-util.h"
35 #include "location-common-util.h"
36 #include "location-privacy.h"
37
38 #include <vconf-internal-location-keys.h>
39
40 /*
41  * forward definitions
42  */
43
44 typedef struct _LocationWpsPrivate {
45         LocationWpsMod          *mod;
46         GMutex                          mutex;
47         gboolean                        is_started;
48         guint                           app_type;
49         gboolean                        set_noti;
50         gboolean                        enabled;
51         guint                           pos_updated_timestamp;
52         guint                           pos_interval;
53         guint                           vel_updated_timestamp;
54         guint                           vel_interval;
55         guint                           loc_updated_timestamp;
56         guint                           loc_interval;
57         guint                           loc_timeout;
58         guint                           dist_updated_timestamp;
59         guint                           min_interval;
60         gdouble                         min_distance;
61         LocationPosition        *pos;
62         LocationVelocity        *vel;
63         LocationAccuracy        *acc;
64         GList                           *boundary_list;
65 } LocationWpsPrivate;
66
67 enum {
68         PROP_0,
69         PROP_METHOD_TYPE,
70         PROP_IS_STARTED,
71         PROP_LAST_POSITION,
72         PROP_POS_INTERVAL,
73         PROP_VEL_INTERVAL,
74         PROP_LOC_INTERVAL,
75         PROP_BOUNDARY,
76         PROP_REMOVAL_BOUNDARY,
77         PROP_MIN_INTERVAL,
78         PROP_MIN_DISTANCE,
79         PROP_SERVICE_STATUS,
80         PROP_MAX
81 };
82
83 static guint32 signals[LAST_SIGNAL] = {0, };
84 static GParamSpec *properties[PROP_MAX] = {NULL, };
85
86 #define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), LOCATION_TYPE_WPS, LocationWpsPrivate))
87
88 static void location_ielement_interface_init(LocationIElementInterface *iface);
89
90 G_DEFINE_TYPE_WITH_CODE(LocationWps, location_wps, G_TYPE_OBJECT,
91                                                 G_IMPLEMENT_INTERFACE(LOCATION_TYPE_IELEMENT, location_ielement_interface_init));
92
93 static void
94 __reset_pos_data_from_priv(LocationWpsPrivate *priv)
95 {
96         LOC_FUNC_LOG
97         g_return_if_fail(priv);
98
99         if (priv->pos) {
100                 location_position_free(priv->pos);
101                 priv->pos = NULL;
102         }
103         if (priv->vel) {
104                 location_velocity_free(priv->vel);
105                 priv->vel = NULL;
106         }
107         if (priv->acc) {
108                 location_accuracy_free(priv->acc);
109                 priv->acc = NULL;
110         }
111         priv->pos_updated_timestamp = 0;
112         priv->vel_updated_timestamp = 0;
113 }
114
115 static gboolean
116 __get_started(gpointer self)
117 {
118         LocationWpsPrivate *priv = GET_PRIVATE(self);
119         g_return_val_if_fail(priv, FALSE);
120
121         return priv->is_started;
122 }
123
124 static int
125 __set_started(gpointer self, gboolean started)
126 {
127         LocationWpsPrivate *priv = GET_PRIVATE(self);
128         g_return_val_if_fail(priv, -1);
129
130         if (priv->is_started != started) {
131                 g_mutex_lock(&priv->mutex);
132                 priv->is_started = started;
133                 g_mutex_unlock(&priv->mutex);
134         }
135
136         return 0;
137 }
138
139 static void
140 wps_status_cb(gboolean enabled, LocationStatus status, gpointer self)
141 {
142         LOCATION_LOGD("status = %d, status");
143         g_return_if_fail(self);
144         LocationWpsPrivate *priv = GET_PRIVATE(self);
145         g_return_if_fail(priv);
146         if (priv->enabled == TRUE && enabled == FALSE) {
147                 __set_started(self, FALSE);
148                 enable_signaling(self, signals, &(priv->enabled), enabled, status);
149         }
150 }
151
152 static void
153 wps_location_cb(gboolean enabled, LocationPosition *pos, LocationVelocity *vel, LocationAccuracy *acc, gpointer self)
154 {
155         g_return_if_fail(self);
156         g_return_if_fail(pos);
157         g_return_if_fail(vel);
158         g_return_if_fail(acc);
159         LocationWpsPrivate *priv = GET_PRIVATE(self);
160         g_return_if_fail(priv);
161
162         if (priv->min_interval != LOCATION_UPDATE_INTERVAL_NONE) {
163                 distance_based_position_signaling(self,
164                                                                                 signals,
165                                                                                 enabled,
166                                                                                 pos,
167                                                                                 vel,
168                                                                                 acc,
169                                                                                 priv->min_interval,
170                                                                                 priv->min_distance,
171                                                                                 &(priv->enabled),
172                                                                                 &(priv->dist_updated_timestamp),
173                                                                                 &(priv->pos),
174                                                                                 &(priv->vel),
175                                                                                 &(priv->acc));
176         }
177         location_signaling(self,
178                                         signals,
179                                         enabled,
180                                         priv->boundary_list,
181                                         pos,
182                                         vel,
183                                         acc,
184                                         priv->pos_interval,
185                                         priv->vel_interval,
186                                         priv->loc_interval,
187                                         &(priv->enabled),
188                                         &(priv->pos_updated_timestamp),
189                                         &(priv->vel_updated_timestamp),
190                                         &(priv->loc_updated_timestamp),
191                                         &(priv->pos),
192                                         &(priv->vel),
193                                         &(priv->acc));
194 }
195
196 static void
197 location_setting_wps_cb(keynode_t *key, gpointer self)
198 {
199         LOC_FUNC_LOG
200         g_return_if_fail(key);
201         g_return_if_fail(self);
202         LocationWpsPrivate *priv = GET_PRIVATE(self);
203         g_return_if_fail(priv);
204         g_return_if_fail(priv->mod);
205         g_return_if_fail(priv->mod->handler);
206
207         int ret = LOCATION_ERROR_NONE;
208
209         if (location_setting_get_key_val(key) == 0) {
210                 if (priv->mod->ops.stop && __get_started(self)) {
211                         __set_started(self, FALSE);
212                         ret = priv->mod->ops.stop(priv->mod->handler);
213                         if (ret == LOCATION_ERROR_NONE)
214                                 __reset_pos_data_from_priv(priv);
215                 }
216         } else {
217                 if (1 == location_setting_get_int(VCONFKEY_LOCATION_NETWORK_ENABLED) && priv->mod->ops.start && !__get_started(self)) {
218                         LOCATION_LOGD("location resumed by setting");
219                         __set_started(self, TRUE);
220                         ret = priv->mod->ops.start(priv->mod->handler, wps_status_cb, wps_location_cb, self);
221                         if (ret != LOCATION_ERROR_NONE) {
222                                 __set_started(self, FALSE);
223                                 LOCATION_LOGD("Fail to start. Error[%d]", ret);
224                         }
225                 }
226         }
227
228 }
229
230 static int
231 location_wps_start(LocationWps *self)
232 {
233         LOC_FUNC_LOG
234         LocationWpsPrivate *priv = GET_PRIVATE(self);
235         g_return_val_if_fail(priv, LOCATION_ERROR_NOT_AVAILABLE);
236         g_return_val_if_fail(priv->mod, LOCATION_ERROR_NOT_AVAILABLE);
237         g_return_val_if_fail(priv->mod->handler, LOCATION_ERROR_NOT_AVAILABLE);
238         g_return_val_if_fail(priv->mod->ops.start, LOCATION_ERROR_NOT_AVAILABLE);
239
240         if (__get_started(self) == TRUE) return LOCATION_ERROR_NONE;
241
242         int ret = LOCATION_ERROR_NONE;
243
244         if (!location_setting_get_int(VCONFKEY_LOCATION_NETWORK_ENABLED)) {
245                 ret = LOCATION_ERROR_SETTING_OFF;
246         } else {
247                 __set_started(self, TRUE);
248                 ret = priv->mod->ops.start(priv->mod->handler, wps_status_cb, wps_location_cb, self);
249                 if (ret != LOCATION_ERROR_NONE) {
250                         __set_started(self, FALSE);
251                         LOCATION_LOGE("Fail to start wps. Error[%d]", ret);
252                         return ret;
253                 }
254         }
255
256         if (priv->app_type != CPPAPP && priv->set_noti == FALSE) {
257                 location_setting_add_notify(VCONFKEY_LOCATION_NETWORK_ENABLED, location_setting_wps_cb, self);
258                 priv->set_noti = TRUE;
259         }
260
261         return ret;
262 }
263
264 static int
265 location_wps_stop(LocationWps *self)
266 {
267         LOC_FUNC_LOG
268         LocationWpsPrivate *priv = GET_PRIVATE(self);
269         g_return_val_if_fail(priv, LOCATION_ERROR_NOT_AVAILABLE);
270         g_return_val_if_fail(priv->mod, LOCATION_ERROR_NOT_AVAILABLE);
271         g_return_val_if_fail(priv->mod->handler, LOCATION_ERROR_NOT_AVAILABLE);
272         g_return_val_if_fail(priv->mod->ops.stop, LOCATION_ERROR_NOT_AVAILABLE);
273
274         int ret = LOCATION_ERROR_NONE;
275
276         if (__get_started(self) == TRUE) {
277                 __set_started(self, FALSE);
278                 ret = priv->mod->ops.stop(priv->mod->handler);
279                 LOC_IF_FAIL_LOG(ret, _E, "Failed to stop [%s]", err_msg(ret));
280         }
281
282         if (priv->app_type != CPPAPP && priv->set_noti == TRUE) {
283                 location_setting_ignore_notify(VCONFKEY_LOCATION_NETWORK_ENABLED, location_setting_wps_cb);
284                 priv->set_noti = FALSE;
285         }
286
287         __reset_pos_data_from_priv(priv);
288
289         return ret;
290 }
291
292 static void
293 location_wps_dispose(GObject *gobject)
294 {
295         LOC_FUNC_LOG
296         LocationWpsPrivate *priv = GET_PRIVATE(gobject);
297         g_return_if_fail(priv);
298
299         g_mutex_clear(&priv->mutex);
300         if (priv->app_type != CPPAPP && priv->set_noti == TRUE) {
301                 location_setting_ignore_notify(VCONFKEY_LOCATION_NETWORK_ENABLED, location_setting_wps_cb);
302                 priv->set_noti = FALSE;
303
304         }
305
306         G_OBJECT_CLASS(location_wps_parent_class)->dispose(gobject);
307 }
308
309 static void
310 location_wps_finalize(GObject *gobject)
311 {
312         LOC_FUNC_LOG
313         LocationWpsPrivate *priv = GET_PRIVATE(gobject);
314         g_return_if_fail(priv);
315         module_free(priv->mod, "wps");
316
317         if (priv->boundary_list) {
318                 g_list_free_full(priv->boundary_list, free_boundary_list);
319                 priv->boundary_list = NULL;
320         }
321
322         if (priv->pos) {
323                 location_position_free(priv->pos);
324                 priv->pos = NULL;
325         }
326
327         if (priv->vel) {
328                 location_velocity_free(priv->vel);
329                 priv->vel = NULL;
330         }
331
332         if (priv->acc) {
333                 location_accuracy_free(priv->acc);
334                 priv->acc = NULL;
335         }
336         G_OBJECT_CLASS(location_wps_parent_class)->finalize(gobject);
337 }
338
339 static void
340 location_wps_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
341 {
342         LocationWpsPrivate *priv = GET_PRIVATE(object);
343         g_return_if_fail(priv);
344         int ret = 0;
345
346         switch (property_id) {
347         case PROP_BOUNDARY: {
348                                 GList *boundary_list = (GList *)g_list_copy(g_value_get_pointer(value));
349                                 ret = set_prop_boundary(&priv->boundary_list, boundary_list);
350                                 LOC_IF_FAIL_LOG(ret, _E, "Set boundary [%s]", err_msg(ret));
351                                 if (boundary_list) g_list_free(boundary_list);
352                                 break;
353                         }
354         case PROP_REMOVAL_BOUNDARY: {
355                                 LocationBoundary *req_boundary = (LocationBoundary *) g_value_dup_boxed(value);
356                                 ret = set_prop_removal_boundary(&priv->boundary_list, req_boundary);
357                                 LOC_IF_FAIL_LOG(ret, _E, "Set removal boundary [%s]", err_msg(ret));
358                                 break;
359                         }
360         case PROP_POS_INTERVAL: {
361                                 guint interval = g_value_get_uint(value);
362                                 if (interval > 0) {
363                                         if (interval < LOCATION_UPDATE_INTERVAL_MAX)
364                                                 priv->pos_interval = interval;
365                                         else
366                                                 priv->pos_interval = (guint)LOCATION_UPDATE_INTERVAL_MAX;
367                                 } else
368                                         priv->pos_interval = (guint)LOCATION_UPDATE_INTERVAL_DEFAULT;
369
370                                 break;
371                         }
372         case PROP_VEL_INTERVAL: {
373                                 guint interval = g_value_get_uint(value);
374                                 if (interval > 0) {
375                                         if (interval < LOCATION_UPDATE_INTERVAL_MAX)
376                                                 priv->vel_interval = interval;
377                                         else
378                                                 priv->vel_interval = (guint)LOCATION_UPDATE_INTERVAL_MAX;
379                                 } else {
380                                         priv->vel_interval = (guint)LOCATION_UPDATE_INTERVAL_DEFAULT;
381                                 }
382                                 break;
383                         }
384         case PROP_LOC_INTERVAL: {
385                                 guint interval = g_value_get_uint(value);
386                                 LOCATION_LOGD("Set prop>> PROP_LOC_INTERVAL: %u", interval);
387                                 if (interval > 0) {
388                                         if (interval < LOCATION_UPDATE_INTERVAL_MAX)
389                                                 priv->loc_interval = interval;
390                                         else
391                                                 priv->loc_interval = (guint)LOCATION_UPDATE_INTERVAL_MAX;
392                                 } else
393                                         priv->loc_interval = (guint)LOCATION_UPDATE_INTERVAL_DEFAULT;
394
395                                 break;
396                         }
397         case PROP_MIN_INTERVAL: {
398                                 guint interval = g_value_get_uint(value);
399                                 LOCATION_LOGD("Set prop>> update-min-interval: %u", interval);
400                                 if (interval > 0) {
401                                         if (interval < LOCATION_MIN_INTERVAL_MAX)
402                                                 priv->min_interval = interval;
403                                         else
404                                                 priv->min_interval = (guint)LOCATION_MIN_INTERVAL_MAX;
405                                 } else
406                                         priv->min_interval = (guint)LOCATION_MIN_INTERVAL_DEFAULT;
407
408                                 break;
409                         }
410         case PROP_MIN_DISTANCE: {
411                                 gdouble distance = g_value_get_double(value);
412                                 LOCATION_LOGD("Set prop>> update-min-distance: %u", distance);
413                                 if (distance > 0) {
414                                         if (distance < LOCATION_MIN_DISTANCE_MAX)
415                                                 priv->min_distance = distance;
416                                         else
417                                                 priv->min_distance = (gdouble)LOCATION_MIN_DISTANCE_MAX;
418                                 } else
419                                         priv->min_distance = (gdouble)LOCATION_MIN_DISTANCE_DEFAULT;
420
421                                 break;
422                         }
423         case PROP_SERVICE_STATUS: {
424                                 gint enabled = g_value_get_int(value);
425                                 LOCATION_LOGD("Set prop>> PROP_SERVICE_STATUS: %u", enabled);
426                                 priv->enabled = enabled;
427                                 break;
428                         }
429         default:
430                         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
431                         break;
432         }
433 }
434
435 static void
436 location_wps_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
437 {
438         LocationWpsPrivate *priv = GET_PRIVATE(object);
439         g_return_if_fail(priv);
440
441         switch (property_id) {
442         case PROP_METHOD_TYPE:
443                         g_value_set_int(value, LOCATION_METHOD_WPS);
444                         break;
445         case PROP_IS_STARTED:
446                         g_value_set_boolean(value, __get_started(object));
447                         break;
448         case PROP_LAST_POSITION:
449                         g_value_set_boxed(value, priv->pos);
450                         break;
451         case PROP_BOUNDARY:
452                         g_value_set_pointer(value, g_list_first(priv->boundary_list));
453                         break;
454         case PROP_POS_INTERVAL:
455                         g_value_set_uint(value, priv->pos_interval);
456                         break;
457         case PROP_VEL_INTERVAL:
458                         g_value_set_uint(value, priv->vel_interval);
459                         break;
460         case PROP_LOC_INTERVAL:
461                         g_value_set_uint(value, priv->loc_interval);
462                         break;
463         case PROP_MIN_INTERVAL:
464                         g_value_set_uint(value, priv->min_interval);
465                         break;
466         case PROP_MIN_DISTANCE:
467                         g_value_set_double(value, priv->min_distance);
468                         break;
469         case PROP_SERVICE_STATUS:
470                         g_value_set_int(value, priv->enabled);
471                         break;
472         default:
473                         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
474                         break;
475         }
476 }
477
478 static int
479 location_wps_get_position(LocationWps *self, LocationPosition **position, LocationAccuracy **accuracy)
480 {
481         int ret = LOCATION_ERROR_NOT_AVAILABLE;
482
483         LocationWpsPrivate *priv = GET_PRIVATE(self);
484         g_return_val_if_fail(priv, LOCATION_ERROR_NOT_AVAILABLE);
485         g_return_val_if_fail(priv->mod, LOCATION_ERROR_NOT_AVAILABLE);
486         setting_retval_if_fail(VCONFKEY_LOCATION_NETWORK_ENABLED);
487
488         if (__get_started(self) != TRUE) {
489                 LOCATION_LOGE("location is not started");
490                 return LOCATION_ERROR_NOT_AVAILABLE;
491         }
492
493         if (priv->pos) {
494                 *position = location_position_copy(priv->pos);
495                 if (priv->acc) *accuracy = location_accuracy_copy(priv->acc);
496                 else *accuracy = location_accuracy_new(LOCATION_ACCURACY_LEVEL_NONE, 0.0, 0.0);
497                 ret = LOCATION_ERROR_NONE;
498         }
499
500         return ret;
501 }
502
503 static int
504 location_wps_get_position_ext(LocationWps *self, LocationPosition **position, LocationVelocity **velocity, LocationAccuracy **accuracy)
505 {
506         int ret = LOCATION_ERROR_NOT_AVAILABLE;
507
508         LocationWpsPrivate *priv = GET_PRIVATE(self);
509         g_return_val_if_fail(priv, LOCATION_ERROR_NOT_AVAILABLE);
510         g_return_val_if_fail(priv->mod, LOCATION_ERROR_NOT_AVAILABLE);
511         setting_retval_if_fail(VCONFKEY_LOCATION_NETWORK_ENABLED);
512
513         LOC_COND_RET(__get_started(self) != TRUE, LOCATION_ERROR_NOT_AVAILABLE, _E, "location is not started [%s]", err_msg(LOCATION_ERROR_NOT_AVAILABLE));
514
515         if (priv->pos && priv->vel) {
516                 *position = location_position_copy(priv->pos);
517                 *velocity = location_velocity_copy(priv->vel);
518                 if (priv->acc) *accuracy = location_accuracy_copy(priv->acc);
519                 else *accuracy = location_accuracy_new(LOCATION_ACCURACY_LEVEL_NONE, 0.0, 0.0);
520                 ret = LOCATION_ERROR_NONE;
521         }
522
523         return ret;
524 }
525
526
527 static int
528 location_wps_get_last_position(LocationWps *self, LocationPosition **position, LocationAccuracy **accuracy)
529 {
530         LocationWpsPrivate *priv = GET_PRIVATE(self);
531         g_return_val_if_fail(priv, LOCATION_ERROR_NOT_AVAILABLE);
532         g_return_val_if_fail(priv->mod, LOCATION_ERROR_NOT_AVAILABLE);
533         setting_retval_if_fail(VCONFKEY_LOCATION_NETWORK_ENABLED);
534
535         int ret = LOCATION_ERROR_NONE;
536         LocationVelocity *_velocity = NULL;
537
538         LocModWpsOps ops = priv->mod->ops;
539         g_return_val_if_fail(priv->mod->handler, LOCATION_ERROR_NOT_AVAILABLE);
540         g_return_val_if_fail(ops.get_last_position, LOCATION_ERROR_NOT_AVAILABLE);
541
542         ret = ops.get_last_position(priv->mod->handler, position, &_velocity, accuracy);
543         if (_velocity) location_velocity_free(_velocity);
544
545         return ret;
546 }
547
548 static int
549 location_wps_get_last_position_ext(LocationWps *self, LocationPosition **position, LocationVelocity **velocity, LocationAccuracy **accuracy)
550 {
551         LocationWpsPrivate *priv = GET_PRIVATE(self);
552         g_return_val_if_fail(priv, LOCATION_ERROR_NOT_AVAILABLE);
553         g_return_val_if_fail(priv->mod, LOCATION_ERROR_NOT_AVAILABLE);
554         setting_retval_if_fail(VCONFKEY_LOCATION_NETWORK_ENABLED);
555
556         LocModWpsOps ops = priv->mod->ops;
557         g_return_val_if_fail(priv->mod->handler, LOCATION_ERROR_NOT_AVAILABLE);
558         g_return_val_if_fail(ops.get_last_position, LOCATION_ERROR_NOT_AVAILABLE);
559
560         return ops.get_last_position(priv->mod->handler, position, velocity, accuracy);
561 }
562
563
564 static int
565 location_wps_get_velocity(LocationWps *self, LocationVelocity **velocity, LocationAccuracy **accuracy)
566 {
567         int ret = LOCATION_ERROR_NOT_AVAILABLE;
568         LocationWpsPrivate *priv = GET_PRIVATE(self);
569         g_return_val_if_fail(priv, LOCATION_ERROR_NOT_AVAILABLE);
570         g_return_val_if_fail(priv->mod, LOCATION_ERROR_NOT_AVAILABLE);
571         setting_retval_if_fail(VCONFKEY_LOCATION_NETWORK_ENABLED);
572
573         LOC_COND_RET(__get_started(self) != TRUE, LOCATION_ERROR_NOT_AVAILABLE, _E, "location is not started [%s]", err_msg(LOCATION_ERROR_NOT_AVAILABLE));
574
575         if (priv->vel) {
576                 *velocity = location_velocity_copy(priv->vel);
577                 if (priv->acc) *accuracy = location_accuracy_copy(priv->acc);
578                 else *accuracy = location_accuracy_new(LOCATION_ACCURACY_LEVEL_NONE, 0.0, 0.0);
579                 ret = LOCATION_ERROR_NONE;
580         }
581
582         return ret;
583 }
584
585 static int
586 location_wps_get_last_velocity(LocationWps *self, LocationVelocity **velocity, LocationAccuracy **accuracy)
587 {
588         LocationWpsPrivate *priv = GET_PRIVATE(self);
589         g_return_val_if_fail(priv, LOCATION_ERROR_NOT_AVAILABLE);
590         g_return_val_if_fail(priv->mod, LOCATION_ERROR_NOT_AVAILABLE);
591         setting_retval_if_fail(VCONFKEY_LOCATION_NETWORK_ENABLED);
592
593         int ret = LOCATION_ERROR_NONE;
594         LocationPosition *_position = NULL;
595
596         LocModWpsOps ops = priv->mod->ops;
597         g_return_val_if_fail(priv->mod->handler, LOCATION_ERROR_NOT_AVAILABLE);
598         ret = ops.get_last_position(priv->mod->handler, &_position, velocity, accuracy);
599         if (!_position) location_position_free(_position);
600
601         return ret;
602 }
603
604 static gboolean __single_location_timeout_cb(void *data)
605 {
606         LOC_FUNC_LOG
607         LocationWps *self = (LocationWps *)data;
608         LocationWpsPrivate *priv = GET_PRIVATE(self);
609         g_return_val_if_fail(priv, FALSE);
610
611         LocationPosition *pos = location_position_new(0, 0.0, 0.0, 0.0, LOCATION_STATUS_NO_FIX);
612         LocationVelocity *vel = location_velocity_new(0, 0.0, 0.0, 0.0);
613         LocationAccuracy *acc = location_accuracy_new(LOCATION_ACCURACY_LEVEL_NONE, 0.0, 0.0);
614
615         if (priv->loc_timeout) g_source_remove(priv->loc_timeout);
616         priv->loc_timeout = 0;
617
618         g_signal_emit(self, signals[LOCATION_UPDATED], 0, LOCATION_ERROR_NOT_AVAILABLE, pos, vel, acc);
619         location_wps_stop(self);
620
621         return FALSE;
622 }
623
624
625 static void
626 wps_single_location_cb(gboolean enabled, LocationPosition *pos, LocationVelocity *vel, LocationAccuracy *acc, gpointer self)
627 {
628         LOC_FUNC_LOG
629         g_return_if_fail(self);
630         g_return_if_fail(pos);
631         g_return_if_fail(vel);
632         g_return_if_fail(acc);
633
634         LocationWpsPrivate *priv = GET_PRIVATE(self);
635         g_return_if_fail(priv);
636
637         g_signal_emit(self, signals[LOCATION_UPDATED], 0, LOCATION_ERROR_NONE, pos, vel, acc);
638         if (priv->loc_timeout) {
639                 g_source_remove(priv->loc_timeout);
640                 priv->loc_timeout = 0;
641         }
642         location_wps_stop(self);
643 }
644
645 static int
646 location_wps_request_single_location(LocationWps *self, int timeout)
647 {
648         LOC_FUNC_LOG
649         LocationWpsPrivate *priv = GET_PRIVATE(self);
650         g_return_val_if_fail(priv, LOCATION_ERROR_NOT_AVAILABLE);
651         g_return_val_if_fail(priv->mod, LOCATION_ERROR_NOT_AVAILABLE);
652         g_return_val_if_fail(priv->mod->handler, LOCATION_ERROR_NOT_AVAILABLE);
653         g_return_val_if_fail(priv->mod->ops.start, LOCATION_ERROR_NOT_AVAILABLE);
654
655         if (__get_started(self) == TRUE) return LOCATION_ERROR_NONE;
656
657         int ret = LOCATION_ERROR_NONE;
658
659         __set_started(self, TRUE);
660         ret = priv->mod->ops.start(priv->mod->handler, wps_status_cb, wps_single_location_cb, self);
661         if (ret != LOCATION_ERROR_NONE) {
662                 LOCATION_LOGE("Fail to start request single. Error[%d]", ret);
663                 __set_started(self, FALSE);
664                 return ret;
665         } else {
666                 if (priv->loc_timeout != 0)
667                         g_source_remove(priv->loc_timeout);
668
669                 priv->loc_timeout = g_timeout_add_seconds(timeout, __single_location_timeout_cb, self);
670         }
671
672         return ret;
673 }
674
675 static int
676 location_wps_get_satellite(LocationWps *self, LocationSatellite **satellite)
677 {
678         return LOCATION_ERROR_NOT_SUPPORTED;
679 }
680
681 static int
682 location_wps_get_last_satellite(LocationWps *self, LocationSatellite **satellite)
683 {
684         return LOCATION_ERROR_NOT_SUPPORTED;
685 }
686
687 static int
688 location_wps_set_option(LocationWps *self, const char *option)
689 {
690         LocationWpsPrivate *priv = GET_PRIVATE(self);
691         g_return_val_if_fail(priv, LOCATION_ERROR_NOT_AVAILABLE);
692         g_return_val_if_fail(priv->mod, LOCATION_ERROR_NOT_AVAILABLE);
693         g_return_val_if_fail(priv->mod->handler, LOCATION_ERROR_NOT_AVAILABLE);
694
695         return LOCATION_ERROR_NONE;
696 }
697
698 static int
699 location_wps_get_nmea(LocationWps *self, char **nmea_data)
700 {
701         return LOCATION_ERROR_NOT_SUPPORTED;
702 }
703
704 static void
705 location_ielement_interface_init(LocationIElementInterface *iface)
706 {
707         iface->start = (TYPE_START_FUNC)location_wps_start;
708         iface->stop = (TYPE_STOP_FUNC)location_wps_stop;
709         iface->get_position = (TYPE_GET_POSITION)location_wps_get_position;
710         iface->get_position_ext = (TYPE_GET_POSITION_EXT)location_wps_get_position_ext;
711         iface->get_last_position = (TYPE_GET_POSITION)location_wps_get_last_position;
712         iface->get_last_position_ext = (TYPE_GET_POSITION_EXT)location_wps_get_last_position_ext;
713         iface->get_velocity = (TYPE_GET_VELOCITY)location_wps_get_velocity;
714         iface->get_last_velocity = (TYPE_GET_VELOCITY)location_wps_get_last_velocity;
715         iface->get_satellite = (TYPE_GET_SATELLITE)location_wps_get_satellite;
716         iface->get_last_satellite = (TYPE_GET_SATELLITE)location_wps_get_last_satellite;
717         iface->set_option = (TYPE_SET_OPTION)location_wps_set_option;
718         iface->request_single_location = (TYPE_REQUEST_SINGLE_LOCATION)location_wps_request_single_location;
719         iface->get_nmea = (TYPE_GET_NMEA)location_wps_get_nmea;
720 }
721
722 static void
723 location_wps_init(LocationWps *self)
724 {
725         LOC_FUNC_LOG
726         LocationWpsPrivate *priv = GET_PRIVATE(self);
727         g_return_if_fail(priv);
728
729         priv->mod = (LocationWpsMod *)module_new("wps");
730         if (!priv->mod) LOCATION_LOGW("module loading failed");
731
732         g_mutex_init(&priv->mutex);
733         priv->is_started = FALSE;
734         priv->set_noti = FALSE;
735         priv->enabled = FALSE;
736
737         priv->pos_interval = LOCATION_UPDATE_INTERVAL_DEFAULT;
738         priv->vel_interval = LOCATION_UPDATE_INTERVAL_DEFAULT;
739         priv->loc_interval = LOCATION_UPDATE_INTERVAL_DEFAULT;
740         priv->min_interval = LOCATION_UPDATE_INTERVAL_NONE;
741
742         priv->pos_updated_timestamp = 0;
743         priv->vel_updated_timestamp = 0;
744         priv->loc_updated_timestamp = 0;
745
746         priv->pos = NULL;
747         priv->vel = NULL;
748         priv->acc = NULL;
749         priv->boundary_list = NULL;
750
751         priv->loc_timeout = 0;
752
753         priv->app_type = location_get_app_type(NULL);
754         if (priv->app_type == 0)
755                 LOCATION_LOGW("Fail to get app_type");
756 }
757
758 static void
759 location_wps_class_init(LocationWpsClass *klass)
760 {
761         LOC_FUNC_LOG
762         GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
763
764         gobject_class->set_property = location_wps_set_property;
765         gobject_class->get_property = location_wps_get_property;
766
767         gobject_class->dispose = location_wps_dispose;
768         gobject_class->finalize = location_wps_finalize;
769
770         g_type_class_add_private(klass, sizeof(LocationWpsPrivate));
771
772         signals[SERVICE_ENABLED] = g_signal_new("service-enabled",
773                                                                                         G_TYPE_FROM_CLASS(klass),
774                                                                                         G_SIGNAL_RUN_FIRST |
775                                                                                         G_SIGNAL_NO_RECURSE,
776                                                                                         G_STRUCT_OFFSET(LocationWpsClass, enabled),
777                                                                                         NULL, NULL,
778                                                                                         location_VOID__UINT,
779                                                                                         G_TYPE_NONE, 1,
780                                                                                         G_TYPE_UINT);
781
782         signals[SERVICE_DISABLED] = g_signal_new("service-disabled",
783                                                                                         G_TYPE_FROM_CLASS(klass),
784                                                                                         G_SIGNAL_RUN_FIRST |
785                                                                                         G_SIGNAL_NO_RECURSE,
786                                                                                         G_STRUCT_OFFSET(LocationWpsClass, disabled),
787                                                                                         NULL, NULL,
788                                                                                         location_VOID__UINT,
789                                                                                         G_TYPE_NONE, 1,
790                                                                                         G_TYPE_UINT);
791
792 #if 0 /* TODO: STATUS_CHANGED will aggregate SERVICE_ENABLED and SERVICE_DISABLED */
793         signals[STATUS_CHANGED] = g_signal_new("status-changed",
794                                                                                         G_TYPE_FROM_CLASS(klass),
795                                                                                         G_SIGNAL_RUN_FIRST |
796                                                                                         G_SIGNAL_NO_RECURSE,
797                                                                                         G_STRUCT_OFFSET(LocationWpsClass, status_changed),
798                                                                                         NULL, NULL,
799                                                                                         location_VOID__UINT,
800                                                                                         G_TYPE_NONE, 1,
801                                                                                         G_TYPE_UINT);
802 #endif
803
804         signals[SERVICE_UPDATED] = g_signal_new("service-updated",
805                                                                                         G_TYPE_FROM_CLASS(klass),
806                                                                                         G_SIGNAL_RUN_FIRST |
807                                                                                         G_SIGNAL_NO_RECURSE,
808                                                                                         G_STRUCT_OFFSET(LocationWpsClass, service_updated),
809                                                                                         NULL, NULL,
810                                                                                         location_VOID__INT_POINTER_POINTER_POINTER,
811                                                                                         G_TYPE_NONE, 4,
812                                                                                         G_TYPE_INT,
813                                                                                         G_TYPE_POINTER,
814                                                                                         G_TYPE_POINTER,
815                                                                                         G_TYPE_POINTER);
816
817         signals[LOCATION_UPDATED] = g_signal_new("location-updated",
818                                                                                         G_TYPE_FROM_CLASS(klass),
819                                                                                         G_SIGNAL_RUN_FIRST |
820                                                                                         G_SIGNAL_NO_RECURSE,
821                                                                                         G_STRUCT_OFFSET(LocationWpsClass, location_updated),
822                                                                                         NULL, NULL,
823                                                                                         location_VOID__INT_POINTER_POINTER_POINTER,
824                                                                                         G_TYPE_NONE, 4,
825                                                                                         G_TYPE_INT,
826                                                                                         G_TYPE_POINTER,
827                                                                                         G_TYPE_POINTER,
828                                                                                         G_TYPE_POINTER);
829
830         signals[ZONE_IN] = g_signal_new("zone-in",
831                                                                         G_TYPE_FROM_CLASS(klass),
832                                                                         G_SIGNAL_RUN_FIRST |
833                                                                         G_SIGNAL_NO_RECURSE,
834                                                                         G_STRUCT_OFFSET(LocationWpsClass, zone_in),
835                                                                         NULL, NULL,
836                                                                         location_VOID__POINTER_POINTER_POINTER,
837                                                                         G_TYPE_NONE, 3,
838                                                                         G_TYPE_POINTER,
839                                                                         G_TYPE_POINTER,
840                                                                         G_TYPE_POINTER);
841
842         signals[ZONE_OUT] = g_signal_new("zone-out",
843                                                                         G_TYPE_FROM_CLASS(klass),
844                                                                         G_SIGNAL_RUN_FIRST |
845                                                                         G_SIGNAL_NO_RECURSE,
846                                                                         G_STRUCT_OFFSET(LocationWpsClass, zone_out),
847                                                                         NULL, NULL,
848                                                                         location_VOID__POINTER_POINTER_POINTER,
849                                                                         G_TYPE_NONE, 3,
850                                                                         G_TYPE_POINTER,
851                                                                         G_TYPE_POINTER,
852                                                                         G_TYPE_POINTER);
853
854         properties[PROP_METHOD_TYPE] = g_param_spec_int("method",
855                                                                                                         "method type",
856                                                                                                         "location method type name",
857                                                                                                         LOCATION_METHOD_WPS,
858                                                                                                         LOCATION_METHOD_WPS,
859                                                                                                         LOCATION_METHOD_WPS,
860                                                                                                         G_PARAM_READABLE);
861
862         properties[PROP_IS_STARTED] = g_param_spec_boolean("is_started",
863                                                                                                         "wps is started prop",
864                                                                                                         "wps is started status",
865                                                                                                         FALSE,
866                                                                                                         G_PARAM_READWRITE);
867
868         properties[PROP_LAST_POSITION] = g_param_spec_boxed("last-position",
869                                                                                                                 "wps last position prop",
870                                                                                                                 "wps last position data",
871                                                                                                                 LOCATION_TYPE_POSITION,
872                                                                                                                 G_PARAM_READABLE);
873
874         properties[PROP_POS_INTERVAL] = g_param_spec_uint("pos-interval",
875                                                                                                         "wps position interval prop",
876                                                                                                         "wps position interval data",
877                                                                                                         LOCATION_UPDATE_INTERVAL_MIN,
878                                                                                                         LOCATION_UPDATE_INTERVAL_MAX,
879                                                                                                         LOCATION_UPDATE_INTERVAL_DEFAULT,
880                                                                                                         G_PARAM_READWRITE);
881
882         properties[PROP_VEL_INTERVAL] = g_param_spec_uint("vel-interval",
883                                                                                                         "wps velocity interval prop",
884                                                                                                         "wps velocity interval data",
885                                                                                                         LOCATION_UPDATE_INTERVAL_MIN,
886                                                                                                         LOCATION_UPDATE_INTERVAL_MAX,
887                                                                                                         LOCATION_UPDATE_INTERVAL_DEFAULT,
888                                                                                                         G_PARAM_READWRITE);
889
890         properties[PROP_LOC_INTERVAL] = g_param_spec_uint("loc-interval",
891                                                                                                         "gps location interval prop",
892                                                                                                         "gps location interval data",
893                                                                                                         LOCATION_UPDATE_INTERVAL_MIN,
894                                                                                                         LOCATION_UPDATE_INTERVAL_MAX,
895                                                                                                         LOCATION_UPDATE_INTERVAL_DEFAULT,
896                                                                                                         G_PARAM_READWRITE);
897
898         properties[PROP_MIN_INTERVAL] = g_param_spec_uint("min-interval",
899                                                                                                         "wps distance-based interval prop",
900                                                                                                         "wps distance-based interval data",
901                                                                                                         LOCATION_MIN_INTERVAL_MIN,
902                                                                                                         LOCATION_MIN_INTERVAL_MAX,
903                                                                                                         LOCATION_MIN_INTERVAL_DEFAULT,
904                                                                                                         G_PARAM_READWRITE);
905
906         properties[PROP_MIN_DISTANCE] = g_param_spec_double("min-distance",
907                                                                                                                 "wps distance-based distance prop",
908                                                                                                                 "wps distance-based distance data",
909                                                                                                                 LOCATION_MIN_DISTANCE_MIN,
910                                                                                                                 LOCATION_MIN_DISTANCE_MAX,
911                                                                                                                 LOCATION_MIN_DISTANCE_DEFAULT,
912                                                                                                                 G_PARAM_READWRITE);
913
914         properties[PROP_BOUNDARY] = g_param_spec_pointer("boundary",
915                                                                                                         "wps boundary prop",
916                                                                                                         "wps boundary data",
917                                                                                                         G_PARAM_READWRITE);
918
919         properties[PROP_REMOVAL_BOUNDARY] = g_param_spec_boxed("removal-boundary",
920                                                                                                                 "wps removal boundary prop",
921                                                                                                                 "wps removal boundary data",
922                                                                                                                 LOCATION_TYPE_BOUNDARY,
923                                                                                                                 G_PARAM_READWRITE);
924
925         /* Tizen 3.0 */
926         properties[PROP_SERVICE_STATUS] = g_param_spec_int("service-status",
927                                                                                                         "location service status prop",
928                                                                                                         "location service status data",
929                                                                                                         LOCATION_STATUS_NO_FIX,
930                                                                                                         LOCATION_STATUS_3D_FIX,
931                                                                                                         LOCATION_STATUS_NO_FIX,
932                                                                                                         G_PARAM_READABLE);
933
934         g_object_class_install_properties(gobject_class,
935                                                                         PROP_MAX,
936                                                                         properties);
937 }
938