1. Change tag style for error log
[platform/core/location/lbs-location.git] / location / manager / location-mock.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-mock.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 _LocationMockPrivate {
45         LocationMockMod         *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 } LocationMockPrivate;
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_MOCK, LocationMockPrivate))
87
88 static void location_ielement_interface_init(LocationIElementInterface *iface);
89
90 G_DEFINE_TYPE_WITH_CODE(LocationMock, location_mock, G_TYPE_OBJECT,
91                                                 G_IMPLEMENT_INTERFACE(LOCATION_TYPE_IELEMENT,
92                                                                                           location_ielement_interface_init));
93
94 static void
95 __reset_pos_data_from_priv(LocationMockPrivate *priv)
96 {
97         LOC_FUNC_LOG
98         g_return_if_fail(priv);
99
100         if (priv->pos) {
101                 location_position_free(priv->pos);
102                 priv->pos = NULL;
103         }
104         if (priv->vel) {
105                 location_velocity_free(priv->vel);
106                 priv->vel = NULL;
107         }
108         if (priv->acc) {
109                 location_accuracy_free(priv->acc);
110                 priv->acc = NULL;
111         }
112         priv->pos_updated_timestamp = 0;
113         priv->vel_updated_timestamp = 0;
114 }
115
116 static gboolean
117 __get_started(gpointer self)
118 {
119         LocationMockPrivate *priv = GET_PRIVATE(self);
120         g_return_val_if_fail(priv, FALSE);
121
122         return priv->is_started;
123 }
124
125 static int
126 __set_started(gpointer self, gboolean started)
127 {
128         LocationMockPrivate *priv = GET_PRIVATE(self);
129         g_return_val_if_fail(priv, -1);
130
131         if (priv->is_started != started) {
132                 g_mutex_lock(&priv->mutex);
133                 priv->is_started = started;
134                 g_mutex_unlock(&priv->mutex);
135         }
136
137         return 0;
138 }
139
140 static void
141 mock_status_cb(gboolean enabled, LocationStatus status, gpointer self)
142 {
143         LOC_FUNC_LOG
144         g_return_if_fail(self);
145         LocationMockPrivate *priv = GET_PRIVATE(self);
146         g_return_if_fail(priv);
147         if (priv->enabled == TRUE && enabled == FALSE) {
148                 __set_started(self, FALSE);
149                 enable_signaling(self, signals, &(priv->enabled), enabled, status);
150         }
151 }
152
153 static void
154 mock_location_cb(gboolean enabled, LocationPosition *pos, LocationVelocity *vel, LocationAccuracy *acc, gpointer self)
155 {
156         g_return_if_fail(self);
157         g_return_if_fail(pos);
158         g_return_if_fail(vel);
159         g_return_if_fail(acc);
160         LocationMockPrivate *priv = GET_PRIVATE(self);
161         g_return_if_fail(priv);
162
163         if (priv->min_interval != LOCATION_UPDATE_INTERVAL_NONE) {
164                 distance_based_position_signaling(self,
165                                                                                 signals,
166                                                                                 enabled,
167                                                                                 pos,
168                                                                                 vel,
169                                                                                 acc,
170                                                                                 priv->min_interval,
171                                                                                 priv->min_distance,
172                                                                                 &(priv->enabled),
173                                                                                 &(priv->dist_updated_timestamp),
174                                                                                 &(priv->pos),
175                                                                                 &(priv->vel),
176                                                                                 &(priv->acc));
177         }
178
179         LOCATION_LOGD("Calling location_signaling, status =%d", pos->status);
180
181         location_signaling(self,
182                                                 signals,
183                                                 enabled,
184                                                 priv->boundary_list,
185                                                 pos,
186                                                 vel,
187                                                 acc,
188                                                 priv->pos_interval,
189                                                 priv->vel_interval,
190                                                 priv->loc_interval,
191                                                 &(priv->enabled),
192                                                 &(priv->pos_updated_timestamp),
193                                                 &(priv->vel_updated_timestamp),
194                                                 &(priv->loc_updated_timestamp),
195                                                 &(priv->pos),
196                                                 &(priv->vel),
197                                                 &(priv->acc));
198 }
199
200 static void
201 location_setting_mock_cb(keynode_t *key, gpointer self)
202 {
203         LOC_FUNC_LOG
204         g_return_if_fail(key);
205         g_return_if_fail(self);
206         LocationMockPrivate *priv = GET_PRIVATE(self);
207         g_return_if_fail(priv);
208         g_return_if_fail(priv->mod);
209         g_return_if_fail(priv->mod->handler);
210
211         int ret = LOCATION_ERROR_NONE;
212
213         if (location_setting_get_key_val(key) == 0) {
214                 if (priv->mod->ops.stop && __get_started(self)) {
215                         __set_started(self, FALSE);
216                         ret = priv->mod->ops.stop(priv->mod->handler);
217                         if (ret == LOCATION_ERROR_NONE)
218                                 __reset_pos_data_from_priv(priv);
219                 }
220         } else {
221                 if (location_setting_get_int(VCONFKEY_LOCATION_MOCK_ENABLED) == 1 && priv->mod->ops.start && !__get_started(self)) {
222                         LOCATION_LOGD("location resumed by setting");
223                         __set_started(self, TRUE);
224                         ret = priv->mod->ops.start(priv->mod->handler, mock_status_cb, mock_location_cb, self);
225                         if (ret != LOCATION_ERROR_NONE) {
226                                 __set_started(self, FALSE);
227                                 LOCATION_LOGD("Fail to start. Error[%d]", ret);
228                         }
229                 }
230         }
231
232 }
233
234 static int
235 location_mock_start(LocationMock *self)
236 {
237         LOC_FUNC_LOG
238         LocationMockPrivate *priv = GET_PRIVATE(self);
239         g_return_val_if_fail(priv, LOCATION_ERROR_NOT_AVAILABLE);
240         g_return_val_if_fail(priv->mod, LOCATION_ERROR_NOT_AVAILABLE);
241         g_return_val_if_fail(priv->mod->handler, LOCATION_ERROR_NOT_AVAILABLE);
242         g_return_val_if_fail(priv->mod->ops.start, LOCATION_ERROR_NOT_AVAILABLE);
243
244         if (__get_started(self) == TRUE) return LOCATION_ERROR_NONE;
245
246         int ret = LOCATION_ERROR_NONE;
247
248         if (!location_setting_get_int(VCONFKEY_LOCATION_MOCK_ENABLED)) {
249                 ret = LOCATION_ERROR_SETTING_OFF;
250         } else {
251                 __set_started(self, TRUE);
252                 ret = priv->mod->ops.start(priv->mod->handler, mock_status_cb, mock_location_cb, self);
253                 if (ret != LOCATION_ERROR_NONE) {
254                         __set_started(self, FALSE);
255                         LOCATION_LOGE("Failed to start mock. Error[%d]", ret);
256                         return ret;
257                 }
258         }
259
260         if (priv->app_type != CPPAPP && priv->set_noti == FALSE) {
261                 location_setting_add_notify(VCONFKEY_LOCATION_MOCK_ENABLED, location_setting_mock_cb, self);
262                 priv->set_noti = TRUE;
263         }
264         LOCATION_LOGD("EXIT <<<, ret = %d", ret);
265
266         return ret;
267 }
268
269 static int
270 location_mock_stop(LocationMock *self)
271 {
272         LOC_FUNC_LOG
273         LocationMockPrivate *priv = GET_PRIVATE(self);
274         g_return_val_if_fail(priv, LOCATION_ERROR_NOT_AVAILABLE);
275         g_return_val_if_fail(priv->mod, LOCATION_ERROR_NOT_AVAILABLE);
276         g_return_val_if_fail(priv->mod->handler, LOCATION_ERROR_NOT_AVAILABLE);
277         g_return_val_if_fail(priv->mod->ops.stop, LOCATION_ERROR_NOT_AVAILABLE);
278
279         int ret = LOCATION_ERROR_NONE;
280
281         if (__get_started(self) == TRUE) {
282                 __set_started(self, FALSE);
283                 ret = priv->mod->ops.stop(priv->mod->handler);
284                 LOC_IF_FAIL_LOG(ret, _E, "Failed to stop [%s]", err_msg(ret));
285         }
286
287         if (priv->app_type != CPPAPP && priv->set_noti == TRUE) {
288                 location_setting_ignore_notify(VCONFKEY_LOCATION_MOCK_ENABLED, location_setting_mock_cb);
289                 priv->set_noti = FALSE;
290         }
291
292         __reset_pos_data_from_priv(priv);
293
294         return ret;
295 }
296
297 static void
298 location_mock_dispose(GObject *gobject)
299 {
300         LOC_FUNC_LOG
301         LocationMockPrivate *priv = GET_PRIVATE(gobject);
302         g_return_if_fail(priv);
303
304         g_mutex_clear(&priv->mutex);
305         if (priv->app_type != CPPAPP && priv->set_noti == TRUE) {
306                 location_setting_ignore_notify(VCONFKEY_LOCATION_MOCK_ENABLED, location_setting_mock_cb);
307                 priv->set_noti = FALSE;
308
309         }
310
311         G_OBJECT_CLASS(location_mock_parent_class)->dispose(gobject);
312 }
313
314 static void
315 location_mock_finalize(GObject *gobject)
316 {
317         LOC_FUNC_LOG
318         LocationMockPrivate *priv = GET_PRIVATE(gobject);
319         g_return_if_fail(priv);
320         module_free(priv->mod, "mock");
321
322         if (priv->boundary_list) {
323                 g_list_free_full(priv->boundary_list, free_boundary_list);
324                 priv->boundary_list = NULL;
325         }
326
327         if (priv->pos) {
328                 location_position_free(priv->pos);
329                 priv->pos = NULL;
330         }
331
332         if (priv->vel) {
333                 location_velocity_free(priv->vel);
334                 priv->vel = NULL;
335         }
336
337         if (priv->acc) {
338                 location_accuracy_free(priv->acc);
339                 priv->acc = NULL;
340         }
341
342         G_OBJECT_CLASS(location_mock_parent_class)->finalize(gobject);
343 }
344
345 static void
346 location_mock_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
347 {
348         LocationMockPrivate *priv = GET_PRIVATE(object);
349         g_return_if_fail(priv);
350         int ret = 0;
351
352         switch (property_id) {
353         case PROP_BOUNDARY: {
354                                 GList *boundary_list = (GList *)g_list_copy(g_value_get_pointer(value));
355                                 ret = set_prop_boundary(&priv->boundary_list, boundary_list);
356                                 LOC_IF_FAIL_LOG(ret, _E, "Set boundary. Error[%s]", err_msg(ret));
357                                 if (boundary_list) g_list_free(boundary_list);
358                                 break;
359                         }
360         case PROP_REMOVAL_BOUNDARY: {
361                                 LocationBoundary *req_boundary = (LocationBoundary *) g_value_dup_boxed(value);
362                                 ret = set_prop_removal_boundary(&priv->boundary_list, req_boundary);
363                                 LOC_IF_FAIL_LOG(ret, _E, "Set removal boundary. Error[%s]", err_msg(ret));
364                                 break;
365                         }
366         case PROP_POS_INTERVAL: {
367                                 guint interval = g_value_get_uint(value);
368                                 if (interval > 0) {
369                                         if (interval < LOCATION_UPDATE_INTERVAL_MAX)
370                                                 priv->pos_interval = interval;
371                                         else
372                                                 priv->pos_interval = (guint)LOCATION_UPDATE_INTERVAL_MAX;
373                                 } else
374                                         priv->pos_interval = (guint)LOCATION_UPDATE_INTERVAL_DEFAULT;
375
376                                 break;
377                         }
378         case PROP_VEL_INTERVAL: {
379                                 guint interval = g_value_get_uint(value);
380                                 if (interval > 0) {
381                                         if (interval < LOCATION_UPDATE_INTERVAL_MAX)
382                                                 priv->vel_interval = interval;
383                                         else
384                                                 priv->vel_interval = (guint)LOCATION_UPDATE_INTERVAL_MAX;
385                                 } else {
386                                         priv->vel_interval = (guint)LOCATION_UPDATE_INTERVAL_DEFAULT;
387                                 }
388                                 break;
389                         }
390         case PROP_LOC_INTERVAL: {
391                                 guint interval = g_value_get_uint(value);
392                                 LOCATION_LOGD("Set prop>> PROP_LOC_INTERVAL: %u", interval);
393                                 if (interval > 0) {
394                                         if (interval < LOCATION_UPDATE_INTERVAL_MAX)
395                                                 priv->loc_interval = interval;
396                                         else
397                                                 priv->loc_interval = (guint)LOCATION_UPDATE_INTERVAL_MAX;
398                                 } else
399                                         priv->loc_interval = (guint)LOCATION_UPDATE_INTERVAL_DEFAULT;
400
401                                 break;
402                         }
403         case PROP_MIN_INTERVAL: {
404                                 guint interval = g_value_get_uint(value);
405                                 LOCATION_LOGD("Set prop>> update-min-interval: %u", interval);
406                                 if (interval > 0) {
407                                         if (interval < LOCATION_MIN_INTERVAL_MAX)
408                                                 priv->min_interval = interval;
409                                         else
410                                                 priv->min_interval = (guint)LOCATION_MIN_INTERVAL_MAX;
411                                 } else
412                                         priv->min_interval = (guint)LOCATION_MIN_INTERVAL_DEFAULT;
413
414                                 break;
415                         }
416         case PROP_MIN_DISTANCE: {
417                                 gdouble distance = g_value_get_double(value);
418                                 LOCATION_LOGD("Set prop>> update-min-distance: %u", distance);
419                                 if (distance > 0) {
420                                         if (distance < LOCATION_MIN_DISTANCE_MAX)
421                                                 priv->min_distance = distance;
422                                         else
423                                                 priv->min_distance = (gdouble)LOCATION_MIN_DISTANCE_MAX;
424                                 } else
425                                         priv->min_distance = (gdouble)LOCATION_MIN_DISTANCE_DEFAULT;
426
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_mock_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
437 {
438         LocationMockPrivate *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_MOCK);
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_mock_get_position(LocationMock *self, LocationPosition **position, LocationAccuracy **accuracy)
480 {
481         int ret = LOCATION_ERROR_NOT_AVAILABLE;
482
483         LocationMockPrivate *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_MOCK_ENABLED);
487
488         LOC_COND_RET(__get_started(self) != TRUE, LOCATION_ERROR_NOT_AVAILABLE, _E, "location is not started [%s]", err_msg(LOCATION_ERROR_NOT_AVAILABLE));
489
490         if (priv->pos) {
491                 *position = location_position_copy(priv->pos);
492                 if (priv->acc) *accuracy = location_accuracy_copy(priv->acc);
493                 else *accuracy = location_accuracy_new(LOCATION_ACCURACY_LEVEL_NONE, 0.0, 0.0);
494                 ret = LOCATION_ERROR_NONE;
495         }
496
497         return ret;
498 }
499
500 static int
501 location_mock_get_position_ext(LocationMock *self, LocationPosition **position, LocationVelocity **velocity, LocationAccuracy **accuracy)
502 {
503         int ret = LOCATION_ERROR_NOT_AVAILABLE;
504
505         LocationMockPrivate *priv = GET_PRIVATE(self);
506         g_return_val_if_fail(priv, LOCATION_ERROR_NOT_AVAILABLE);
507         g_return_val_if_fail(priv->mod, LOCATION_ERROR_NOT_AVAILABLE);
508         setting_retval_if_fail(VCONFKEY_LOCATION_MOCK_ENABLED);
509
510         LOC_COND_RET(__get_started(self) != TRUE, LOCATION_ERROR_NOT_AVAILABLE, _E, "location is not started [%s]", err_msg(LOCATION_ERROR_NOT_AVAILABLE));
511
512         if (priv->pos && priv->vel) {
513                 *position = location_position_copy(priv->pos);
514                 *velocity = location_velocity_copy(priv->vel);
515                 if (priv->acc)
516                         *accuracy = location_accuracy_copy(priv->acc);
517                 else
518                         *accuracy = location_accuracy_new(LOCATION_ACCURACY_LEVEL_NONE, 0.0, 0.0);
519
520                 ret = LOCATION_ERROR_NONE;
521         }
522
523         return ret;
524 }
525
526
527 static int
528 location_mock_get_last_position(LocationMock *self, LocationPosition **position, LocationAccuracy **accuracy)
529 {
530         LocationMockPrivate *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_MOCK_ENABLED);
534
535         int ret = LOCATION_ERROR_NONE;
536         LocationVelocity *_velocity = NULL;
537
538         LocModMockOps 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_mock_get_last_position_ext(LocationMock *self, LocationPosition **position, LocationVelocity **velocity, LocationAccuracy **accuracy)
550 {
551         LocationMockPrivate *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_MOCK_ENABLED);
555
556         LocModMockOps 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_mock_get_velocity(LocationMock *self, LocationVelocity **velocity, LocationAccuracy **accuracy)
566 {
567         int ret = LOCATION_ERROR_NOT_AVAILABLE;
568
569         LocationMockPrivate *priv = GET_PRIVATE(self);
570         g_return_val_if_fail(priv, LOCATION_ERROR_NOT_AVAILABLE);
571         g_return_val_if_fail(priv->mod, LOCATION_ERROR_NOT_AVAILABLE);
572         setting_retval_if_fail(VCONFKEY_LOCATION_MOCK_ENABLED);
573
574         LOC_COND_RET(__get_started(self) != TRUE, LOCATION_ERROR_NOT_AVAILABLE, _E, "location is not started [%s]", err_msg(LOCATION_ERROR_NOT_AVAILABLE));
575
576         if (priv->vel) {
577                 *velocity = location_velocity_copy(priv->vel);
578                 if (priv->acc) *accuracy = location_accuracy_copy(priv->acc);
579                 else *accuracy = location_accuracy_new(LOCATION_ACCURACY_LEVEL_NONE, 0.0, 0.0);
580                 ret = LOCATION_ERROR_NONE;
581         }
582
583         return ret;
584 }
585
586 static int
587 location_mock_get_last_velocity(LocationMock *self, LocationVelocity **velocity, LocationAccuracy **accuracy)
588 {
589         LocationMockPrivate *priv = GET_PRIVATE(self);
590         g_return_val_if_fail(priv, LOCATION_ERROR_NOT_AVAILABLE);
591         g_return_val_if_fail(priv->mod, LOCATION_ERROR_NOT_AVAILABLE);
592         setting_retval_if_fail(VCONFKEY_LOCATION_MOCK_ENABLED);
593
594         int ret = LOCATION_ERROR_NONE;
595         LocationPosition *_position = NULL;
596
597         LocModMockOps ops = priv->mod->ops;
598         g_return_val_if_fail(priv->mod->handler, LOCATION_ERROR_NOT_AVAILABLE);
599         ret = ops.get_last_position(priv->mod->handler, &_position, velocity, accuracy);
600         if (!_position) location_position_free(_position);
601
602         return ret;
603 }
604
605 static gboolean
606 __single_location_timeout_cb(void *data)
607 {
608         LOC_FUNC_LOG
609         LocationMock *self = (LocationMock *)data;
610         LocationMockPrivate *priv = GET_PRIVATE(self);
611         g_return_val_if_fail(priv, FALSE);
612
613         LocationPosition *pos = location_position_new(0, 0.0, 0.0, 0.0, LOCATION_STATUS_NO_FIX);
614         LocationVelocity *vel = location_velocity_new(0, 0.0, 0.0, 0.0);
615         LocationAccuracy *acc = location_accuracy_new(LOCATION_ACCURACY_LEVEL_NONE, 0.0, 0.0);
616
617         if (priv->loc_timeout) g_source_remove(priv->loc_timeout);
618         priv->loc_timeout = 0;
619
620         g_signal_emit(self, signals[LOCATION_UPDATED], 0, LOCATION_ERROR_NOT_AVAILABLE, pos, vel, acc);
621         location_mock_stop(self);
622
623         return FALSE;
624 }
625
626
627 static void
628 mock_single_location_cb(gboolean enabled, LocationPosition *pos, LocationVelocity *vel, LocationAccuracy *acc, gpointer self)
629 {
630         LOC_FUNC_LOG
631         g_return_if_fail(self);
632         g_return_if_fail(pos);
633         g_return_if_fail(vel);
634         g_return_if_fail(acc);
635
636         LocationMockPrivate *priv = GET_PRIVATE(self);
637         g_return_if_fail(priv);
638
639         g_signal_emit(self, signals[LOCATION_UPDATED], 0, LOCATION_ERROR_NONE, pos, vel, acc);
640         if (priv->loc_timeout) {
641                 g_source_remove(priv->loc_timeout);
642                 priv->loc_timeout = 0;
643         }
644         location_mock_stop(self);
645 }
646
647 static int
648 location_mock_request_single_location(LocationMock *self, int timeout)
649 {
650         LOC_FUNC_LOG
651         LocationMockPrivate *priv = GET_PRIVATE(self);
652         g_return_val_if_fail(priv, LOCATION_ERROR_NOT_AVAILABLE);
653         g_return_val_if_fail(priv->mod, LOCATION_ERROR_NOT_AVAILABLE);
654         g_return_val_if_fail(priv->mod->handler, LOCATION_ERROR_NOT_AVAILABLE);
655         g_return_val_if_fail(priv->mod->ops.start, LOCATION_ERROR_NOT_AVAILABLE);
656
657         if (__get_started(self) == TRUE) return LOCATION_ERROR_NONE;
658
659         int ret = LOCATION_ERROR_NONE;
660
661         __set_started(self, TRUE);
662         ret = priv->mod->ops.start(priv->mod->handler, mock_status_cb, mock_single_location_cb, self);
663         if (ret != LOCATION_ERROR_NONE) {
664                 LOCATION_LOGE("Fail to start request single. Error[%d]", ret);
665                 __set_started(self, FALSE);
666                 return ret;
667         } else {
668                 if (priv->loc_timeout != 0)
669                         g_source_remove(priv->loc_timeout);
670
671                 priv->loc_timeout = g_timeout_add_seconds(timeout, __single_location_timeout_cb, self);
672         }
673
674         return ret;
675 }
676
677 static int
678 location_mock_get_satellite(LocationMock *self, LocationSatellite **satellite)
679 {
680         return LOCATION_ERROR_NOT_SUPPORTED;
681 }
682
683 static int
684 location_mock_get_last_satellite(LocationMock *self, LocationSatellite **satellite)
685 {
686         return LOCATION_ERROR_NOT_SUPPORTED;
687 }
688
689 static int
690 location_mock_set_option(LocationMock *self, const char *option)
691 {
692         LocationMockPrivate *priv = GET_PRIVATE(self);
693         g_return_val_if_fail(priv, LOCATION_ERROR_NOT_AVAILABLE);
694         g_return_val_if_fail(priv->mod, LOCATION_ERROR_NOT_AVAILABLE);
695         g_return_val_if_fail(priv->mod->handler, LOCATION_ERROR_NOT_AVAILABLE);
696         g_return_val_if_fail(priv->mod->ops.start, LOCATION_ERROR_NOT_AVAILABLE);
697
698         int ret = LOCATION_ERROR_NONE;
699
700         ret = priv->mod->ops.set_option(priv->mod->handler, option);
701         LOC_IF_FAIL_LOG(ret, _E, "Failed to set_option. Error[%d]", ret);
702
703         return ret;
704 }
705
706 static int
707 location_mock_get_nmea(LocationMock *self, char **nmea_data)
708 {
709         return LOCATION_ERROR_NOT_SUPPORTED;
710 }
711
712
713 /* Tizen 3.0 */
714
715 static int
716 location_mock_get_status(LocationMock *self, int *status)
717 {
718         LocationMockPrivate *priv = GET_PRIVATE(self);
719         g_return_val_if_fail(priv->mod->handler, LOCATION_ERROR_NOT_AVAILABLE);
720
721         if (__get_started(self) == TRUE)
722                 *status = 1;
723         else
724                 *status = 0;
725
726         return LOCATION_ERROR_NONE;
727 }
728
729
730 static void
731 __set_mock_location_cb(gboolean enabled, LocationStatus status, gpointer self)
732 {
733         g_return_if_fail(self);
734         LocationObject *obj = (LocationObject *) self;
735         LocationMockPrivate *priv = GET_PRIVATE(obj);
736         g_return_if_fail(priv);
737
738         LOCATION_LOGD("ENTER >>>");
739         LOCATION_LOGD("status = %d");
740         if (status == LOCATION_STATUS_MOCK_FAIL) {
741                 /* g_signal_emit(obj, signals[SERVICE_DISABLED], 0, LOCATION_STATUS_NO_FIX); */
742                 g_signal_emit(obj, signals[STATUS_CHANGED], 0, LOCATION_STATUS_MOCK_FAIL);
743         }
744
745         LOCATION_LOGD("EXIT <<<");
746 }
747
748 static int
749 location_mock_set_mock_location(LocationMock *self, LocationPosition *position, LocationVelocity *velocity, LocationAccuracy *accuracy)
750 {
751         LOC_FUNC_LOG
752         LocationMockPrivate *priv = GET_PRIVATE(self);
753         g_return_val_if_fail(priv->mod->handler, LOCATION_ERROR_NOT_AVAILABLE);
754         g_return_val_if_fail(priv->mod->ops.set_mock_location, LOCATION_ERROR_NOT_AVAILABLE);
755
756         int ret = LOCATION_ERROR_NONE;
757         if (!location_setting_get_int(VCONFKEY_LOCATION_MOCK_ENABLED)) {
758                 ret = LOCATION_ERROR_SETTING_OFF;
759         } else {
760                 ret = priv->mod->ops.set_mock_location(priv->mod->handler, position, velocity, accuracy, __set_mock_location_cb, self);
761                 LOC_IF_FAIL_LOG(ret, _E, "Failed to set_mock_location [%s]", err_msg(ret));
762         }
763
764         return ret;
765 }
766
767 static int
768 location_mock_clear_mock_location(LocationMock *self)
769 {
770         LOC_FUNC_LOG
771         LocationMockPrivate *priv = GET_PRIVATE(self);
772         g_return_val_if_fail(priv->mod->handler, LOCATION_ERROR_NOT_AVAILABLE);
773         g_return_val_if_fail(priv->mod->ops.set_mock_location, LOCATION_ERROR_NOT_AVAILABLE);
774
775         int ret = LOCATION_ERROR_NONE;
776         if (!location_setting_get_int(VCONFKEY_LOCATION_MOCK_ENABLED)) {
777                 ret = LOCATION_ERROR_SETTING_OFF;
778         } else {
779                 ret = priv->mod->ops.clear_mock_location(priv->mod->handler, __set_mock_location_cb, self);
780                 LOC_IF_FAIL_LOG(ret, _E, "Failed to clear_mock_location [%s]", err_msg(ret));
781         }
782
783         return ret;
784 }
785
786 static void _glib_log(const gchar *log_domain, GLogLevelFlags log_level, const gchar *msg, gpointer user_data)
787 {
788         LOCATION_LOGD("GLIB[%d]: %s", log_level, msg);
789 }
790
791
792 static void
793 location_ielement_interface_init(LocationIElementInterface *iface)
794 {
795         iface->start = (TYPE_START_FUNC)location_mock_start;
796         iface->stop = (TYPE_STOP_FUNC)location_mock_stop;
797         iface->get_position = (TYPE_GET_POSITION)location_mock_get_position;
798         iface->get_position_ext = (TYPE_GET_POSITION_EXT)location_mock_get_position_ext;
799         iface->get_last_position = (TYPE_GET_POSITION)location_mock_get_last_position;
800         iface->get_last_position_ext = (TYPE_GET_POSITION_EXT)location_mock_get_last_position_ext;
801         iface->get_velocity = (TYPE_GET_VELOCITY)location_mock_get_velocity;
802         iface->get_last_velocity = (TYPE_GET_VELOCITY)location_mock_get_last_velocity;
803         iface->get_satellite = (TYPE_GET_SATELLITE)location_mock_get_satellite;
804         iface->get_last_satellite = (TYPE_GET_SATELLITE)location_mock_get_last_satellite;
805         iface->set_option = (TYPE_SET_OPTION)location_mock_set_option;
806         iface->request_single_location = (TYPE_REQUEST_SINGLE_LOCATION)location_mock_request_single_location;
807         iface->get_nmea = (TYPE_GET_NMEA)location_mock_get_nmea;
808
809         iface->get_status = (TYPE_GET_STATUS) location_mock_get_status;
810         iface->set_mock_location = (TYPE_SET_MOCK_LOCATION) location_mock_set_mock_location;
811         iface->clear_mock_location = (TYPE_CLEAR_MOCK_LOCATION) location_mock_clear_mock_location;
812 }
813
814 static void
815 location_mock_init(LocationMock *self)
816 {
817         LOC_FUNC_LOG
818         LocationMockPrivate *priv = GET_PRIVATE(self);
819         g_return_if_fail(priv);
820
821         priv->mod = (LocationMockMod *)module_new("mock");
822         LOC_COND_LOG(!priv->mod, _E, "Module loading failed");
823
824         g_mutex_init(&priv->mutex);
825         priv->is_started = FALSE;
826         priv->set_noti = FALSE;
827         priv->enabled = FALSE;
828
829         priv->pos_interval = LOCATION_UPDATE_INTERVAL_DEFAULT;
830         priv->vel_interval = LOCATION_UPDATE_INTERVAL_DEFAULT;
831         priv->loc_interval = LOCATION_UPDATE_INTERVAL_DEFAULT;
832         priv->min_interval = LOCATION_UPDATE_INTERVAL_NONE;
833
834         priv->pos_updated_timestamp = 0;
835         priv->vel_updated_timestamp = 0;
836         priv->loc_updated_timestamp = 0;
837
838         priv->pos = NULL;
839         priv->vel = NULL;
840         priv->acc = NULL;
841         priv->boundary_list = NULL;
842
843         priv->loc_timeout = 0;
844
845         priv->app_type = location_get_app_type(NULL);
846         LOC_COND_LOG(priv->app_type == 0, _E, "Fail to get app_type");
847 }
848
849 static void
850 location_mock_class_init(LocationMockClass *klass)
851 {
852         LOC_FUNC_LOG
853
854         GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
855
856         g_log_set_default_handler(_glib_log, NULL);
857
858
859         gobject_class->set_property = location_mock_set_property;
860         gobject_class->get_property = location_mock_get_property;
861
862         gobject_class->dispose = location_mock_dispose;
863         gobject_class->finalize = location_mock_finalize;
864
865         g_type_class_add_private(klass, sizeof(LocationMockPrivate));
866
867
868
869         signals[SERVICE_ENABLED] = g_signal_new("service-enabled",
870                                                                                         G_TYPE_FROM_CLASS(klass),
871                                                                                         G_SIGNAL_RUN_FIRST |
872                                                                                         G_SIGNAL_NO_RECURSE,
873                                                                                         G_STRUCT_OFFSET(LocationMockClass, enabled),
874                                                                                         NULL, NULL,
875                                                                                         location_VOID__UINT,
876                                                                                         G_TYPE_NONE, 1,
877                                                                                         G_TYPE_UINT);
878
879
880
881         signals[SERVICE_DISABLED] = g_signal_new("service-disabled",
882                                                                                         G_TYPE_FROM_CLASS(klass),
883                                                                                         G_SIGNAL_RUN_FIRST |
884                                                                                         G_SIGNAL_NO_RECURSE,
885                                                                                         G_STRUCT_OFFSET(LocationMockClass, disabled),
886                                                                                         NULL, NULL,
887                                                                                         location_VOID__UINT,
888                                                                                         G_TYPE_NONE, 1,
889                                                                                         G_TYPE_UINT);
890
891 #if 0 /* TODO: STATUS_CHANGED will aggregate SERVICE_ENABLED and SERVICE_DISABLED */
892         signals[STATUS_CHANGED] = g_signal_new("status-changed",
893                                                                                         G_TYPE_FROM_CLASS(klass),
894                                                                                         G_SIGNAL_RUN_FIRST |
895                                                                                         G_SIGNAL_NO_RECURSE,
896                                                                                         G_STRUCT_OFFSET(LocationMockClass, status_changed),
897                                                                                         NULL, NULL,
898                                                                                         location_VOID__UINT,
899                                                                                         G_TYPE_NONE, 1,
900                                                                                         G_TYPE_UINT);
901 #endif
902
903         signals[SERVICE_UPDATED] = g_signal_new("service-updated",
904                                                                                         G_TYPE_FROM_CLASS(klass),
905                                                                                         G_SIGNAL_RUN_FIRST |
906                                                                                         G_SIGNAL_NO_RECURSE,
907                                                                                         G_STRUCT_OFFSET(LocationMockClass, service_updated),
908                                                                                         NULL, NULL,
909                                                                                         location_VOID__INT_POINTER_POINTER_POINTER,
910                                                                                         G_TYPE_NONE, 4,
911                                                                                         G_TYPE_INT,
912                                                                                         G_TYPE_POINTER,
913                                                                                         G_TYPE_POINTER,
914                                                                                         G_TYPE_POINTER);
915
916         signals[LOCATION_UPDATED] = g_signal_new("location-updated",
917                                                                                         G_TYPE_FROM_CLASS(klass),
918                                                                                         G_SIGNAL_RUN_FIRST |
919                                                                                         G_SIGNAL_NO_RECURSE,
920                                                                                         G_STRUCT_OFFSET(LocationMockClass, location_updated),
921                                                                                         NULL, NULL,
922                                                                                         location_VOID__INT_POINTER_POINTER_POINTER,
923                                                                                         G_TYPE_NONE, 4,
924                                                                                         G_TYPE_INT,
925                                                                                         G_TYPE_POINTER,
926                                                                                         G_TYPE_POINTER,
927                                                                                         G_TYPE_POINTER);
928
929         signals[ZONE_IN] = g_signal_new("zone-in",
930                                                                         G_TYPE_FROM_CLASS(klass),
931                                                                         G_SIGNAL_RUN_FIRST |
932                                                                         G_SIGNAL_NO_RECURSE,
933                                                                         G_STRUCT_OFFSET(LocationMockClass, zone_in),
934                                                                         NULL, NULL,
935                                                                         location_VOID__POINTER_POINTER_POINTER,
936                                                                         G_TYPE_NONE, 3,
937                                                                         G_TYPE_POINTER,
938                                                                         G_TYPE_POINTER,
939                                                                         G_TYPE_POINTER);
940
941         signals[ZONE_OUT] = g_signal_new("zone-out",
942                                                                         G_TYPE_FROM_CLASS(klass),
943                                                                         G_SIGNAL_RUN_FIRST |
944                                                                         G_SIGNAL_NO_RECURSE,
945                                                                         G_STRUCT_OFFSET(LocationMockClass, zone_out),
946                                                                         NULL, NULL,
947                                                                         location_VOID__POINTER_POINTER_POINTER,
948                                                                         G_TYPE_NONE, 3,
949                                                                         G_TYPE_POINTER,
950                                                                         G_TYPE_POINTER,
951                                                                         G_TYPE_POINTER);
952
953         properties[PROP_METHOD_TYPE] = g_param_spec_int("method",
954                                                                                                         "method type",
955                                                                                                         "location method type name",
956                                                                                                         LOCATION_METHOD_MOCK,
957                                                                                                         LOCATION_METHOD_MOCK,
958                                                                                                         LOCATION_METHOD_MOCK,
959                                                                                                         G_PARAM_READABLE);
960
961         properties[PROP_IS_STARTED] = g_param_spec_boolean("is_started",
962                                                                                                                 "mock is started prop",
963                                                                                                                 "mock is started status",
964                                                                                                                 FALSE,
965                                                                                                                 G_PARAM_READWRITE);
966
967         properties[PROP_LAST_POSITION] = g_param_spec_boxed("last-position",
968                                                                                                                 "mock last position prop",
969                                                                                                                 "mock last position data",
970                                                                                                                 LOCATION_TYPE_POSITION,
971                                                                                                                 G_PARAM_READABLE);
972
973         properties[PROP_POS_INTERVAL] = g_param_spec_uint("pos-interval",
974                                                                                                         "mock position interval prop",
975                                                                                                         "mock position interval data",
976                                                                                                         LOCATION_UPDATE_INTERVAL_MIN,
977                                                                                                         LOCATION_UPDATE_INTERVAL_MAX,
978                                                                                                         LOCATION_UPDATE_INTERVAL_DEFAULT,
979                                                                                                         G_PARAM_READWRITE);
980
981         properties[PROP_VEL_INTERVAL] = g_param_spec_uint("vel-interval",
982                                                                                                         "mock velocity interval prop",
983                                                                                                         "mock velocity interval data",
984                                                                                                         LOCATION_UPDATE_INTERVAL_MIN,
985                                                                                                         LOCATION_UPDATE_INTERVAL_MAX,
986                                                                                                         LOCATION_UPDATE_INTERVAL_DEFAULT,
987                                                                                                         G_PARAM_READWRITE);
988
989         properties[PROP_LOC_INTERVAL] = g_param_spec_uint("loc-interval",
990                                                                                                         "gps location interval prop",
991                                                                                                         "gps location interval data",
992                                                                                                         LOCATION_UPDATE_INTERVAL_MIN,
993                                                                                                         LOCATION_UPDATE_INTERVAL_MAX,
994                                                                                                         LOCATION_UPDATE_INTERVAL_DEFAULT,
995                                                                                                         G_PARAM_READWRITE);
996
997         properties[PROP_MIN_INTERVAL] = g_param_spec_uint("min-interval",
998                                                                                                         "mock distance-based interval prop",
999                                                                                                         "mock distance-based interval data",
1000                                                                                                         LOCATION_MIN_INTERVAL_MIN,
1001                                                                                                         LOCATION_MIN_INTERVAL_MAX,
1002                                                                                                         LOCATION_MIN_INTERVAL_DEFAULT,
1003                                                                                                         G_PARAM_READWRITE);
1004
1005         properties[PROP_MIN_DISTANCE] = g_param_spec_double("min-distance",
1006                                                                                                                 "mock distance-based distance prop",
1007                                                                                                                 "mock distance-based distance data",
1008                                                                                                                 LOCATION_MIN_DISTANCE_MIN,
1009                                                                                                                 LOCATION_MIN_DISTANCE_MAX,
1010                                                                                                                 LOCATION_MIN_DISTANCE_DEFAULT,
1011                                                                                                                 G_PARAM_READWRITE);
1012
1013         properties[PROP_BOUNDARY] = g_param_spec_pointer("boundary",
1014                                                                                                         "mock boundary prop",
1015                                                                                                         "mock boundary data",
1016                                                                                                         G_PARAM_READWRITE);
1017
1018         properties[PROP_REMOVAL_BOUNDARY] = g_param_spec_boxed("removal-boundary",
1019                                                                                                                         "mock removal boundary prop",
1020                                                                                                                         "mock removal boundary data",
1021                                                                                                                         LOCATION_TYPE_BOUNDARY,
1022                                                                                                                         G_PARAM_READWRITE);
1023
1024         /* Tizen 3.0 */
1025         properties[PROP_SERVICE_STATUS] = g_param_spec_int("service-status",
1026                                                                                                         "location service status prop",
1027                                                                                                         "location service status data",
1028                                                                                                         LOCATION_STATUS_NO_FIX,
1029                                                                                                         LOCATION_STATUS_3D_FIX,
1030                                                                                                         LOCATION_STATUS_NO_FIX,
1031                                                                                                         G_PARAM_READABLE);
1032
1033         g_object_class_install_properties(gobject_class, PROP_MAX, properties);
1034 }
1035