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