1. Change tag style for error log
[platform/core/location/lbs-location.git] / location / manager / location-hybrid-mobile.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-hybrid.h"
32 #include "location-marshal.h"
33 #include "location-ielement.h"
34 #include "location-signaling-util.h"
35 #include "location-common-util.h"
36
37 #include "location-gps.h"
38 #include "location-wps.h"
39 /* Tizen 3.0 */
40 #include "location-mock.h"
41
42 typedef struct _LocationHybridPrivate {
43         gboolean                gps_enabled;
44         gboolean                wps_enabled;
45         gint                    signal_type;
46         guint                   pos_updated_timestamp;
47         guint                   pos_interval;
48         guint                   vel_updated_timestamp;
49         guint                   vel_interval;
50         guint                   sat_updated_timestamp;
51         guint                   sat_interval;
52         guint                   dist_updated_timestamp;
53         guint                   min_interval;
54         gdouble                 min_distance;
55         guint                   loc_updated_timestamp;
56         guint                   loc_interval;
57         LocationObject  *gps;
58         LocationObject  *wps;
59         gboolean                enabled;
60         LocationMethod  current_method;
61         LocationPosition *pos;
62         LocationVelocity *vel;
63         LocationAccuracy *acc;
64         LocationSatellite *sat;
65         GList                   *boundary_list;
66         gboolean                set_noti;
67         guint                   pos_timer;
68         guint                   vel_timer;
69
70         /* Tizen 3.0 */
71         gboolean                mock_enabled;
72         LocationObject  *mock;
73 } LocationHybridPrivate;
74
75 enum {
76         PROP_0,
77         PROP_METHOD_TYPE,
78         PROP_LAST_POSITION,
79         PROP_POS_INTERVAL,
80         PROP_VEL_INTERVAL,
81         PROP_SAT_INTERVAL,
82         PROP_LOC_INTERVAL,
83         PROP_BOUNDARY,
84         PROP_REMOVAL_BOUNDARY,
85         PROP_MIN_INTERVAL,
86         PROP_MIN_DISTANCE,
87         PROP_SERVICE_STATUS,
88         PROP_MAX
89 };
90
91 static guint32 signals[LAST_SIGNAL] = {0, };
92 static GParamSpec *properties[PROP_MAX] = {NULL, };
93
94 #define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), LOCATION_TYPE_HYBRID, LocationHybridPrivate))
95
96 static void location_ielement_interface_init(LocationIElementInterface *iface);
97
98 G_DEFINE_TYPE_WITH_CODE(LocationHybrid, location_hybrid, G_TYPE_OBJECT,
99                                                 G_IMPLEMENT_INTERFACE(LOCATION_TYPE_IELEMENT, location_ielement_interface_init));
100
101 static LocationMethod
102 hybrid_get_current_method(LocationHybridPrivate *priv)
103 {
104         g_return_val_if_fail(priv, LOCATION_METHOD_NONE);
105         LOCATION_LOGD("Current Method [%d]", priv->current_method);
106         return priv->current_method;
107 }
108
109 static gboolean
110 hybrid_set_current_method(LocationHybridPrivate *priv, GType g_type)
111 {
112         g_return_val_if_fail(priv, FALSE);
113
114         if (g_type == LOCATION_TYPE_GPS)
115                 priv->current_method = LOCATION_METHOD_GPS;
116         else if (g_type == LOCATION_TYPE_WPS)
117                 priv->current_method = LOCATION_METHOD_WPS;
118         else if (g_type == LOCATION_TYPE_MOCK)
119                 priv->current_method = LOCATION_METHOD_MOCK;
120         else if (g_type == LOCATION_TYPE_HYBRID)
121                 priv->current_method = LOCATION_METHOD_HYBRID;
122         else
123                 return FALSE;
124
125         return TRUE;
126 }
127
128
129 static int
130 hybrid_get_update_method(LocationHybridPrivate *priv)
131 {
132         if (!priv->gps && !priv->wps & !priv->mock) return -1;
133
134         if (priv->gps_enabled)
135                 hybrid_set_current_method(priv, LOCATION_TYPE_GPS);
136         else if (priv->wps_enabled)
137                 hybrid_set_current_method(priv, LOCATION_TYPE_WPS);
138         else if (priv->mock_enabled)
139                 hybrid_set_current_method(priv, LOCATION_TYPE_MOCK);
140         else
141                 hybrid_set_current_method(priv, LOCATION_TYPE_HYBRID);
142
143         return 0;
144 }
145
146 #if 0
147 static LocationObject *
148 hybrid_get_current_object(LocationHybridPrivate *priv)
149 {
150         LocationMethod method = hybrid_get_current_method(priv);
151
152         LocationObject *obj = NULL;
153         switch (method) {
154         case LOCATION_METHOD_GPS:
155                         obj = priv->gps;
156                         break;
157         case LOCATION_METHOD_WPS:
158                         obj = priv->wps;
159                         break;
160         default:
161                         break;
162         }
163
164         return obj;
165 }
166 #endif
167
168 static gboolean /* True : Receive more accurate info. False : Receive less accurate info */
169 hybrid_compare_g_type_method(LocationHybridPrivate *priv, GType g_type)
170 {
171         if (location_setting_get_int(VCONFKEY_LOCATION_MOCK_ENABLED) == 1 &&
172                 location_setting_get_int(VCONFKEY_LOCATION_MOCK_STATE) == VCONFKEY_LOCATION_POSITION_CONNECTED) {
173                 if (g_type == LOCATION_TYPE_MOCK) {
174                         hybrid_set_current_method(priv, LOCATION_TYPE_MOCK);
175                         return TRUE;
176                 }
177         } else {
178                 if (g_type == LOCATION_TYPE_GPS) {
179                         hybrid_set_current_method(priv, LOCATION_TYPE_GPS);
180                         return TRUE;
181                 } else if (g_type == LOCATION_TYPE_WPS &&
182                         (hybrid_get_current_method(priv) == LOCATION_METHOD_WPS || hybrid_get_current_method(priv) == LOCATION_METHOD_MOCK)) {
183                         hybrid_set_current_method(priv, LOCATION_TYPE_WPS);
184                         return TRUE;
185                 }
186         }
187         return FALSE;
188 }
189
190 static gboolean
191 _location_timeout_cb(gpointer data)
192 {
193         GObject *object = (GObject *)data;
194         if (!object) return FALSE;
195         LocationHybridPrivate *priv = GET_PRIVATE(object);
196         g_return_val_if_fail(priv, FALSE);
197
198         LocationPosition *pos = NULL;
199         LocationVelocity *vel = NULL;
200         LocationAccuracy *acc = NULL;
201
202         if (priv->pos)
203                 pos = location_position_copy(priv->pos);
204         else
205                 pos = location_position_new(0, 0.0, 0.0, 0.0, LOCATION_STATUS_NO_FIX);
206
207         if (priv->vel)
208                 vel = location_velocity_copy(priv->vel);
209         else
210                 vel = location_velocity_new(0, 0.0, 0.0, 0.0);
211
212         if (priv->acc)
213                 acc = location_accuracy_copy(priv->acc);
214         else
215                 acc = location_accuracy_new(LOCATION_ACCURACY_LEVEL_NONE, 0.0, 0.0);
216
217         g_signal_emit(object, signals[SERVICE_UPDATED], 0, priv->signal_type, pos, vel, acc);
218         priv->signal_type = 0;
219
220         location_position_free(pos);
221         location_velocity_free(vel);
222         location_accuracy_free(acc);
223
224         return TRUE;
225 }
226
227 static gboolean
228 _position_timeout_cb(gpointer data)
229 {
230         GObject *object = (GObject *)data;
231         if (!object) return FALSE;
232         LocationHybridPrivate *priv = GET_PRIVATE(object);
233         g_return_val_if_fail(priv, FALSE);
234
235         if (priv->pos_interval == priv->vel_interval) {
236                 priv->signal_type |= POSITION_UPDATED;
237                 priv->signal_type |= VELOCITY_UPDATED;
238         } else {
239                 priv->signal_type |= POSITION_UPDATED;
240         }
241         _location_timeout_cb(object);
242
243         return TRUE;
244 }
245
246 static gboolean
247 _velocity_timeout_cb(gpointer data)
248 {
249         GObject *object = (GObject *)data;
250         LocationHybridPrivate *priv = GET_PRIVATE(object);
251         g_return_val_if_fail(priv, FALSE);
252
253         if (priv->pos_interval != priv->vel_interval) {
254                 priv->signal_type |= VELOCITY_UPDATED;
255                 _location_timeout_cb(object);
256         }
257
258         return TRUE;
259 }
260
261 static void
262 location_hybrid_gps_cb(keynode_t *key, gpointer self)
263 {
264         LOC_FUNC_LOG
265         g_return_if_fail(key);
266         g_return_if_fail(self);
267         LocationHybridPrivate *priv = GET_PRIVATE(self);
268         g_return_if_fail(priv);
269         g_return_if_fail(priv->wps);
270
271         gboolean wps_started = FALSE;
272         int ret = LOCATION_ERROR_NONE;
273         int onoff = 0;
274
275         onoff = location_setting_get_key_val(key);
276         if (0 == onoff) {
277                 /* restart WPS when GPS stopped by setting */
278                 g_object_get(priv->wps, "is_started", &wps_started, NULL);
279                 if (wps_started == FALSE && 1 == location_setting_get_int(VCONFKEY_LOCATION_NETWORK_ENABLED)) {
280                         LOCATION_LOGD("GPS stoped by setting, so restart WPS");
281                         ret = location_start(priv->wps);
282                         LOC_COND_VOID(ret != LOCATION_ERROR_NONE, _E, "Fail hybrid/wps location_start : [%s]", err_msg(ret));
283                 }
284         } else if (1 == onoff) {
285                 LOCATION_LOGD("Hybrid GPS resumed by setting");
286
287         } else {
288                 LOCATION_LOGD("Invalid Value[%d]", onoff);
289         }
290
291 }
292
293 static void
294 hybrid_location_updated(GObject *obj,
295                                                 guint error,
296                                                 gpointer position,
297                                                 gpointer velocity,
298                                                 gpointer accuracy,
299                                                 gpointer self)
300 {
301         LocationPosition *pos = (LocationPosition *)position;
302         LocationVelocity *vel = (LocationVelocity *)velocity;
303         LocationAccuracy *acc = (LocationAccuracy *)accuracy;
304
305         LocationHybridPrivate *priv = GET_PRIVATE((LocationHybrid *)self);
306         g_return_if_fail(priv);
307
308         g_signal_emit(self, signals[LOCATION_UPDATED], 0, error, pos, vel, acc);
309 }
310
311 static void
312 hybrid_service_updated(GObject *obj, gint type, gpointer data, gpointer velocity, gpointer accuracy, gpointer self)
313 {
314         LOC_FUNC_LOG
315         LocationPosition *pos = NULL;
316         LocationVelocity *vel = NULL;
317         LocationAccuracy *acc = NULL;
318         LocationSatellite *sat = NULL;
319         gboolean wps_started = FALSE;
320         int ret = LOCATION_ERROR_NONE;
321
322         if (type == SATELLITE_UPDATED) {
323                 sat = (LocationSatellite *)data;
324                 if (!sat->timestamp) return;
325         } else {
326                 pos = (LocationPosition *)data;
327                 vel = (LocationVelocity *)velocity;
328                 acc = (LocationAccuracy *)accuracy;
329                 if (!pos->timestamp) return;
330                 if (!vel->timestamp) return;
331         }
332
333         LocationHybridPrivate *priv = GET_PRIVATE((LocationHybrid *)self);
334         g_return_if_fail(priv);
335
336         GType g_type = G_TYPE_FROM_INSTANCE(obj);
337         if (g_type == LOCATION_TYPE_GPS) {
338                 if (type == SATELLITE_UPDATED) {
339                         satellite_signaling(self, signals, &(priv->enabled), priv->sat_interval, TRUE, &(priv->sat_updated_timestamp), &(priv->sat), sat);
340                         return;
341                 } else if (location_setting_get_int(VCONFKEY_LOCATION_GPS_STATE) == VCONFKEY_LOCATION_GPS_SEARCHING) {
342                         LOCATION_LOGD("Searching GPS");
343
344                         /* restart WPS when GPS not available */
345                         if (priv->wps) g_object_get(priv->wps, "is_started", &wps_started, NULL);
346                         if (priv->wps && wps_started == FALSE) {
347                                 LOCATION_LOGD("Starting WPS");
348                                 ret = location_start(priv->wps);
349                                 LOC_COND_VOID(ret != LOCATION_ERROR_NONE, _E, "Fail hyhrid location_start : [%s]", err_msg(ret));
350                         }
351                         return;
352                 }
353         }
354         /* TODO: Why we need this logic? */
355         else if (g_type == LOCATION_TYPE_WPS &&
356                 location_setting_get_int(VCONFKEY_LOCATION_WPS_STATE) == VCONFKEY_LOCATION_WPS_SEARCHING) {
357                 LOCATION_LOGD("Searching WPS");
358                 return;
359         }
360
361         if (hybrid_compare_g_type_method(priv, g_type)) {
362                 if (priv->pos) location_position_free(priv->pos);
363                 if (priv->vel) location_velocity_free(priv->vel);
364                 if (priv->acc) location_accuracy_free(priv->acc);
365
366                 if (pos) priv->pos = location_position_copy(pos);
367                 if (vel) priv->vel = location_velocity_copy(vel);
368                 if (acc) priv->acc = location_accuracy_copy(acc);
369
370                 if (pos) {
371                         if (!priv->enabled)
372                                 enable_signaling(self, signals, &(priv->enabled), TRUE, pos->status);
373
374                         if (type == DISTANCE_UPDATED) {
375                                 distance_based_position_signaling(self, signals, priv->enabled, pos, vel, acc,
376                                                                   priv->min_interval, priv->min_distance, &(priv->enabled),
377                                                                   &(priv->dist_updated_timestamp), &(priv->pos), &(priv->vel), &(priv->acc));
378                         } else {
379                                 position_velocity_signaling(self, signals, priv->pos_interval, priv->vel_interval, priv->loc_interval,
380                                                                 &(priv->pos_updated_timestamp), &(priv->vel_updated_timestamp), &(priv->loc_updated_timestamp),
381                                                                 priv->boundary_list, pos, vel, acc);
382                         }
383                 }
384
385                 /* if receive GPS position then stop WPS.. */
386                 if (priv->wps) g_object_get(priv->wps, "is_started", &wps_started, NULL);
387                 if (g_type == LOCATION_TYPE_GPS && wps_started == TRUE) {
388                         LOCATION_LOGD("Calling WPS stop");
389                         ret = location_stop(priv->wps);
390                         LOC_COND_VOID(ret != LOCATION_ERROR_NONE, _E, "Fail hyhrid location_stop : [%s]", err_msg(ret));
391                 }
392
393         } else if (g_type == LOCATION_TYPE_WPS
394                 && location_setting_get_int(VCONFKEY_LOCATION_GPS_STATE) == VCONFKEY_LOCATION_GPS_SEARCHING) {
395                 LOCATION_LOGD("g_type is LOCATION_TYPE_WPS and GPS is searching");
396                 hybrid_set_current_method(priv, g_type);
397
398                 if (priv->pos) location_position_free(priv->pos);
399                 if (priv->vel) location_velocity_free(priv->vel);
400                 if (priv->acc) location_accuracy_free(priv->acc);
401
402                 if (pos) priv->pos = location_position_copy(pos);
403                 if (vel) priv->vel = location_velocity_copy(vel);
404                 if (acc) priv->acc = location_accuracy_copy(acc);
405
406                 if (pos) {
407                         if (!priv->enabled)
408                                 enable_signaling(self, signals, &(priv->enabled), TRUE, pos->status);
409
410                         if (type == DISTANCE_UPDATED) {
411                                 distance_based_position_signaling(self, signals, priv->enabled, pos, vel, acc,
412                                                                                                 priv->min_interval, priv->min_distance, &(priv->enabled),
413                                                                                                 &(priv->dist_updated_timestamp), &(priv->pos), &(priv->vel), &(priv->acc));
414                         } else {
415                                 LOCATION_LOGD("position_velocity_signaling");
416                                 position_velocity_signaling(self, signals, priv->pos_interval, priv->vel_interval, priv->loc_interval,
417                                                                                         &(priv->pos_updated_timestamp), &(priv->vel_updated_timestamp), &(priv->loc_updated_timestamp),
418                                                                                         priv->boundary_list, pos, vel, acc);
419                         }
420                 }
421         }
422 }
423
424 static void
425 hybrid_service_enabled(GObject *obj, guint status, gpointer self)
426 {
427         LOC_FUNC_LOG
428         LocationHybridPrivate *priv = GET_PRIVATE((LocationHybrid *)self);
429         g_return_if_fail(priv);
430
431         GType g_type = G_TYPE_FROM_INSTANCE(obj);
432         if (g_type == LOCATION_TYPE_GPS) {
433                 priv->gps_enabled = TRUE;
434         } else if (g_type == LOCATION_TYPE_WPS) {
435                 priv->wps_enabled = TRUE;
436         } else if (g_type == LOCATION_TYPE_MOCK) {
437                 priv->mock_enabled = TRUE;
438         } else {
439                 LOCATION_LOGW("Undefined GType enabled");
440                 return;
441         }
442         hybrid_get_update_method(priv);
443 }
444
445 static void
446 hybrid_service_disabled(GObject *obj, guint status, gpointer self)
447 {
448         LOC_FUNC_LOG
449         LocationHybridPrivate *priv = GET_PRIVATE((LocationHybrid *)self);
450         g_return_if_fail(priv);
451         GType g_type = G_TYPE_FROM_INSTANCE(obj);
452         if (g_type == LOCATION_TYPE_GPS) {
453                 priv->gps_enabled = FALSE;
454         } else if (g_type == LOCATION_TYPE_WPS) {
455                 priv->wps_enabled = FALSE;
456         } else if (g_type == LOCATION_TYPE_MOCK) {
457                 priv->mock_enabled = FALSE;
458         } else {
459                 LOCATION_LOGW("Undefined GType disabled");
460                 return;
461         }
462         hybrid_get_update_method(priv);
463
464         if (location_setting_get_int(VCONFKEY_LOCATION_MOCK_ENABLED) == 1) {
465                 if (!priv->gps_enabled && !priv->wps_enabled && !priv->mock_enabled)
466                         enable_signaling(self, signals, &(priv->enabled), FALSE, status);
467         } else {
468                 if (!priv->gps_enabled && !priv->wps_enabled)
469                         enable_signaling(self, signals, &(priv->enabled), FALSE, status);
470         }
471 }
472
473 #if 0
474 static void
475 hybrid_status_changed(GObject *obj, guint status, gpointer self)
476 {
477         LOCATION_LOGD("status = %d", status);
478         LocationHybridPrivate *priv = GET_PRIVATE((LocationHybrid *)self);
479         g_return_if_fail(priv);
480         GType g_type = G_TYPE_FROM_INSTANCE(obj);
481
482
483         switch (status) {
484         case LOCATION_STATUS_NO_FIX:
485                         if (g_type == LOCATION_TYPE_GPS) {
486                                 priv->gps_enabled = FALSE;
487                         } else if (g_type == LOCATION_TYPE_WPS) {
488                                 priv->wps_enabled = FALSE;
489                         } else if (g_type == LOCATION_TYPE_MOCK) {
490                                 priv->mock_enabled = FALSE;
491                         } else {
492                                 LOCATION_LOGW("Undefined GType disabled");
493                                 return;
494                         }
495                         hybrid_get_update_method(priv);
496                         if (!priv->gps_enabled && !priv->wps_enabled)
497                                 enable_signaling(self, signals, &(priv->enabled), FALSE, status);
498                         break;
499
500         case LOCATION_STATUS_2D_FIX:
501         case LOCATION_STATUS_3D_FIX:
502                         if (g_type == LOCATION_TYPE_GPS) {
503                                 priv->gps_enabled = TRUE;
504                         } else if (g_type == LOCATION_TYPE_WPS) {
505                                 priv->wps_enabled = TRUE;
506                         } else if (g_type == LOCATION_TYPE_MOCK) {
507                                 priv->mock_enabled = TRUE;
508                         } else {
509                                 LOCATION_LOGW("Undefined GType enabled");
510                                 return;
511                         }
512                         hybrid_get_update_method(priv);
513                         break;
514
515         case LOCATION_STATUS_MOCK_SET:
516                         LOCATION_LOGD("Succeeded set mock location!!!");
517                         break;
518
519         case LOCATION_STATUS_MOCK_FAIL:
520                         if (g_type == LOCATION_TYPE_GPS) {
521                                 priv->gps_enabled = FALSE;
522                         } else if (g_type == LOCATION_TYPE_WPS) {
523                                 priv->wps_enabled = FALSE;
524                         } else {
525                                 LOCATION_LOGW("Undefined GType disabled");
526                                 return;
527                         }
528                         hybrid_get_update_method(priv);
529                         if (!priv->gps_enabled && !priv->wps_enabled)
530                                 enable_signaling(self, signals, &(priv->enabled), FALSE, status);
531                         break;
532
533         default:
534                                 LOCATION_LOGW("Undefined status");
535                         break;
536         }
537 }
538 #endif
539
540
541 static int
542 location_hybrid_start(LocationHybrid *self)
543 {
544         LOC_FUNC_LOG
545
546         int ret_gps = LOCATION_ERROR_NONE;
547         int ret_wps = LOCATION_ERROR_NONE;
548         int ret_mock = LOCATION_ERROR_NONE;
549         gboolean gps_started = FALSE;
550         gboolean wps_started = FALSE;
551         gboolean mock_started = FALSE;
552
553         LocationHybridPrivate *priv = GET_PRIVATE(self);
554         g_return_val_if_fail(priv, LOCATION_ERROR_NOT_AVAILABLE);
555         LOC_COND_RET(!priv->gps && !priv->wps, LOCATION_ERROR_NOT_AVAILABLE, _E, "GPS and WPS Object are not created.");
556
557         if (priv->gps) g_object_get(priv->gps, "is_started", &gps_started, NULL);
558         if (priv->wps) g_object_get(priv->wps, "is_started", &wps_started, NULL);
559         if (priv->mock) g_object_get(priv->mock, "is_started", &mock_started, NULL);
560
561         if ((gps_started == TRUE) || (wps_started == TRUE) || (mock_started == TRUE)) {
562                 LOCATION_LOGD("Already started");
563                 return LOCATION_ERROR_NONE;
564         }
565
566         if (priv->gps) ret_gps = location_start(priv->gps);
567         if (priv->wps) ret_wps = location_start(priv->wps);
568         if (priv->mock) ret_mock = location_start(priv->mock);
569
570         if (ret_gps != LOCATION_ERROR_NONE && ret_wps != LOCATION_ERROR_NONE && ret_mock != LOCATION_ERROR_NONE) {
571                 LOCATION_LOGD("ret_gps = %d, ret_wps = %d, ret_mock = %d", ret_gps, ret_wps, ret_mock);
572                 if (ret_gps == LOCATION_ERROR_SECURITY_DENIED || ret_wps == LOCATION_ERROR_SECURITY_DENIED || ret_mock == LOCATION_ERROR_SECURITY_DENIED)
573                         return LOCATION_ERROR_SECURITY_DENIED;
574                 else if (ret_gps == LOCATION_ERROR_SETTING_OFF || ret_wps == LOCATION_ERROR_SETTING_OFF || ret_mock == LOCATION_ERROR_SETTING_OFF)
575                         return LOCATION_ERROR_SETTING_OFF;
576                 else if (ret_gps == LOCATION_ERROR_NOT_ALLOWED || ret_wps == LOCATION_ERROR_NOT_ALLOWED || ret_mock == LOCATION_ERROR_NOT_ALLOWED)
577                         return LOCATION_ERROR_NOT_ALLOWED;
578                 else
579                         return LOCATION_ERROR_NOT_AVAILABLE;
580         }
581
582         if (priv->set_noti == FALSE) {
583                 location_setting_add_notify(VCONFKEY_LOCATION_ENABLED, location_hybrid_gps_cb, self);
584                 priv->set_noti = TRUE;
585         }
586
587         return LOCATION_ERROR_NONE;
588 }
589
590 static int
591 location_hybrid_stop(LocationHybrid *self)
592 {
593         LOC_FUNC_LOG
594
595         LocationHybridPrivate *priv = GET_PRIVATE(self);
596         g_return_val_if_fail(priv, LOCATION_ERROR_NOT_AVAILABLE);
597
598         LOCATION_LOGD("location_hybrid_stop started......!!!");
599
600         int ret_gps = LOCATION_ERROR_NOT_AVAILABLE;
601         int ret_wps = LOCATION_ERROR_NOT_AVAILABLE;
602         int ret_mock = LOCATION_ERROR_NOT_AVAILABLE;
603         gboolean gps_started = FALSE;
604         gboolean wps_started = FALSE;
605         gboolean mock_started = FALSE;
606
607         if (priv->gps) g_object_get(priv->gps, "is_started", &gps_started, NULL);
608         if (priv->wps) g_object_get(priv->wps, "is_started", &wps_started, NULL);
609         if (priv->mock) g_object_get(priv->mock, "is_started", &mock_started, NULL);
610
611         if ((gps_started == FALSE) && (wps_started == FALSE) && (mock_started == FALSE))
612                 return LOCATION_ERROR_NONE;
613
614         if (priv->gps) ret_gps = location_stop(priv->gps);
615         if (priv->wps) ret_wps = location_stop(priv->wps);
616         if (priv->mock) ret_mock = location_stop(priv->mock);
617
618         if (ret_gps != LOCATION_ERROR_NONE && ret_wps != LOCATION_ERROR_NONE && ret_mock != LOCATION_ERROR_NONE)
619                 return LOCATION_ERROR_NOT_AVAILABLE;
620
621         if (priv->pos_timer) g_source_remove(priv->pos_timer);
622         if (priv->vel_timer) g_source_remove(priv->vel_timer);
623         priv->pos_timer = 0;
624         priv->vel_timer = 0;
625
626         if (priv->set_noti == TRUE) {
627                 location_setting_ignore_notify(VCONFKEY_LOCATION_ENABLED, location_hybrid_gps_cb);
628                 priv->set_noti = FALSE;
629         }
630
631         priv->gps_enabled = FALSE;
632         priv->wps_enabled = FALSE;
633         priv->mock_enabled = FALSE;
634
635         return LOCATION_ERROR_NONE;
636 }
637
638 static void
639 location_hybrid_dispose(GObject *gobject)
640 {
641         LOC_FUNC_LOG
642         LocationHybridPrivate *priv = GET_PRIVATE(gobject);
643         g_return_if_fail(priv);
644
645         if (priv->pos_timer) g_source_remove(priv->pos_timer);
646         if (priv->vel_timer) g_source_remove(priv->vel_timer);
647         priv->pos_timer = 0;
648         priv->vel_timer = 0;
649
650         if (priv->set_noti == TRUE) {
651                 location_setting_ignore_notify(VCONFKEY_LOCATION_ENABLED, location_hybrid_gps_cb);
652                 priv->set_noti = FALSE;
653         }
654
655         G_OBJECT_CLASS(location_hybrid_parent_class)->dispose(gobject);
656 }
657
658 static void
659 location_hybrid_finalize(GObject *gobject)
660 {
661         LOC_FUNC_LOG
662         LocationHybridPrivate *priv = GET_PRIVATE(gobject);
663         g_return_if_fail(priv);
664
665         if (priv->gps) {
666                 g_signal_handlers_disconnect_by_func(priv->gps, G_CALLBACK(hybrid_service_enabled), gobject);
667                 g_signal_handlers_disconnect_by_func(priv->gps, G_CALLBACK(hybrid_service_disabled), gobject);
668                 /* g_signal_handlers_disconnect_by_func(priv->gps, G_CALLBACK(hybrid_status_changed), gobject); */
669                 g_signal_handlers_disconnect_by_func(priv->gps, G_CALLBACK(hybrid_service_updated), gobject);
670                 g_signal_handlers_disconnect_by_func(priv->gps, G_CALLBACK(hybrid_location_updated), gobject);
671                 location_free(priv->gps);
672         }
673         if (priv->wps) {
674                 g_signal_handlers_disconnect_by_func(priv->wps, G_CALLBACK(hybrid_service_enabled), gobject);
675                 g_signal_handlers_disconnect_by_func(priv->wps, G_CALLBACK(hybrid_service_disabled), gobject);
676                 /* g_signal_handlers_disconnect_by_func(priv->wps, G_CALLBACK(hybrid_status_changed), gobject); */
677                 g_signal_handlers_disconnect_by_func(priv->wps, G_CALLBACK(hybrid_service_updated), gobject);
678                 g_signal_handlers_disconnect_by_func(priv->wps, G_CALLBACK(hybrid_location_updated), gobject);
679                 location_free(priv->wps);
680         }
681
682         if (priv->mock) {
683                 g_signal_handlers_disconnect_by_func(priv->mock, G_CALLBACK(hybrid_service_enabled), gobject);
684                 g_signal_handlers_disconnect_by_func(priv->mock, G_CALLBACK(hybrid_service_disabled), gobject);
685                 /* g_signal_handlers_disconnect_by_func(priv->mock, G_CALLBACK(hybrid_status_changed), gobject); */
686                 g_signal_handlers_disconnect_by_func(priv->mock, G_CALLBACK(hybrid_service_updated), gobject);
687                 g_signal_handlers_disconnect_by_func(priv->mock, G_CALLBACK(hybrid_location_updated), gobject);
688                 location_free(priv->mock);
689         }
690
691         if (priv->boundary_list) {
692                 g_list_free_full(priv->boundary_list, free_boundary_list);
693                 priv->boundary_list = NULL;
694         }
695
696         if (priv->pos) {
697                 location_position_free(priv->pos);
698                 priv->pos = NULL;
699         }
700
701         if (priv->vel) {
702                 location_velocity_free(priv->vel);
703                 priv->vel = NULL;
704         }
705
706         if (priv->acc) {
707                 location_accuracy_free(priv->acc);
708                 priv->acc = NULL;
709         }
710
711         if (priv->sat) {
712                 location_satellite_free(priv->sat);
713                 priv->sat = NULL;
714         }
715
716         G_OBJECT_CLASS(location_hybrid_parent_class)->finalize(gobject);
717 }
718
719 static void
720 location_hybrid_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
721 {
722         LocationHybridPrivate *priv = GET_PRIVATE(object);
723         g_return_if_fail(priv);
724         if (!priv->gps && !priv->wps) {
725                 LOCATION_LOGW("Set property is not available now");
726                 return;
727         }
728
729         int ret = 0;
730         switch (property_id) {
731         case PROP_BOUNDARY: {
732                                 GList *boundary_list = (GList *)g_list_copy(g_value_get_pointer(value));
733                                 ret = set_prop_boundary(&priv->boundary_list, boundary_list);
734                                 LOC_COND_VOID(ret != LOCATION_ERROR_NONE, _E, "Set boundary. Error[%s]", err_msg(ret));
735                                 break;
736                         }
737         case PROP_REMOVAL_BOUNDARY: {
738                                 LocationBoundary *req_boundary = (LocationBoundary *) g_value_dup_boxed(value);
739                                 ret = set_prop_removal_boundary(&priv->boundary_list, req_boundary);
740                                 LOC_COND_VOID(ret != LOCATION_ERROR_NONE, _E, "Removal boundary. Error[%s]", err_msg(ret));
741                                 break;
742                         }
743         case PROP_POS_INTERVAL: {
744                                 guint interval = g_value_get_uint(value);
745                                 LOCATION_LOGD("Set prop>> PROP_POS_INTERVAL: %u", interval);
746                                 if (interval > 0) {
747                                         if (interval < LOCATION_UPDATE_INTERVAL_MAX)
748                                                 priv->pos_interval = interval;
749                                         else
750                                                 priv->pos_interval = (guint) LOCATION_UPDATE_INTERVAL_MAX;
751                                 } else {
752                                         priv->pos_interval = LOCATION_UPDATE_INTERVAL_DEFAULT;
753                                 }
754
755                                 if (priv->pos_timer) {
756                                         g_source_remove(priv->pos_timer);
757                                         priv->pos_timer = g_timeout_add(priv->pos_interval * 1000, _position_timeout_cb, object);
758                                 }
759
760                                 if (priv->gps) g_object_set(priv->gps, "pos-interval", priv->pos_interval, NULL);
761                                 if (priv->wps) g_object_set(priv->wps, "pos-interval", priv->pos_interval, NULL);
762
763                                 break;
764                         }
765         case PROP_VEL_INTERVAL: {
766                                 guint interval = g_value_get_uint(value);
767                                 LOCATION_LOGD("Set prop>> PROP_VEL_INTERVAL: %u", interval);
768                                 if (interval > 0) {
769                                         if (interval < LOCATION_UPDATE_INTERVAL_MAX)
770                                                 priv->vel_interval = interval;
771                                         else
772                                                 priv->vel_interval = (guint) LOCATION_UPDATE_INTERVAL_MAX;
773
774                                 } else
775                                         priv->vel_interval = LOCATION_UPDATE_INTERVAL_DEFAULT;
776
777                                 if (priv->vel_timer) {
778                                         g_source_remove(priv->vel_timer);
779                                         priv->vel_timer = g_timeout_add(priv->vel_interval * 1000, _velocity_timeout_cb, object);
780                                 }
781
782                                 if (priv->gps) g_object_set(priv->gps, "vel-interval", priv->vel_interval, NULL);
783                                 if (priv->wps) g_object_set(priv->wps, "vel-interval", priv->vel_interval, NULL);
784
785                                 break;
786                         }
787         case PROP_SAT_INTERVAL: {
788                                 guint interval = g_value_get_uint(value);
789                                 LOCATION_LOGD("Set prop>> PROP_SAT_INTERVAL: %u", interval);
790                                 if (interval > 0) {
791                                         if (interval < LOCATION_UPDATE_INTERVAL_MAX)
792                                                 priv->sat_interval = interval;
793                                         else
794                                                 priv->sat_interval = (guint) LOCATION_UPDATE_INTERVAL_MAX;
795
796                                 } else
797                                         priv->sat_interval = LOCATION_UPDATE_INTERVAL_DEFAULT;
798
799                                 break;
800                         }
801         case PROP_LOC_INTERVAL: {
802                                 guint interval = g_value_get_uint(value);
803                                 LOCATION_LOGD("Set prop>> PROP_LOC_INTERVAL: %u", interval);
804                                 if (interval > 0) {
805                                         if (interval < LOCATION_UPDATE_INTERVAL_MAX)
806                                                 priv->loc_interval = interval;
807                                         else
808                                                 priv->loc_interval = (guint)LOCATION_UPDATE_INTERVAL_MAX;
809                                 } else
810                                         priv->loc_interval = (guint)LOCATION_UPDATE_INTERVAL_DEFAULT;
811
812                                 if (priv->gps) g_object_set(priv->gps, "loc-interval", priv->loc_interval, NULL);
813                                 if (priv->wps) g_object_set(priv->wps, "loc-interval", priv->loc_interval, NULL);
814
815                                 break;
816                         }
817         case PROP_MIN_INTERVAL: {
818                                 guint interval = g_value_get_uint(value);
819                                 LOCATION_LOGD("Set prop>> PROP_MIN_INTERVAL: %u", interval);
820                                 if (interval > 0) {
821                                         if (interval < LOCATION_MIN_INTERVAL_MAX)
822                                                 priv->min_interval = interval;
823                                         else
824                                                 priv->min_interval = (guint)LOCATION_MIN_INTERVAL_MAX;
825                                 } else
826                                         priv->min_interval = (guint)LOCATION_MIN_INTERVAL_DEFAULT;
827
828                                 if (priv->gps) g_object_set(priv->gps, "min-interval", priv->min_interval, NULL);
829                                 if (priv->wps) g_object_set(priv->wps, "min-interval", priv->min_interval, NULL);
830
831                                 break;
832                         }
833         case PROP_MIN_DISTANCE: {
834                                 gdouble distance = g_value_get_double(value);
835                                 LOCATION_LOGD("Set prop>> PROP_MIN_DISTANCE: %u", distance);
836                                 if (distance > 0) {
837                                         if (distance < LOCATION_MIN_DISTANCE_MAX)
838                                                 priv->min_distance = distance;
839                                         else
840                                                 priv->min_distance = (gdouble)LOCATION_MIN_DISTANCE_MAX;
841                                 } else
842                                         priv->min_distance = (gdouble)LOCATION_MIN_DISTANCE_DEFAULT;
843
844                                 if (priv->gps) g_object_set(priv->gps, "min-distance", priv->min_distance, NULL);
845                                 if (priv->wps) g_object_set(priv->wps, "min-distance", priv->min_distance, NULL);
846
847                                 break;
848                         }
849         default:
850                         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
851                         break;
852         }
853 }
854
855 static void
856 location_hybrid_get_property(GObject *object, guint property_id, GValue *value,  GParamSpec *pspec)
857 {
858         LocationHybridPrivate *priv = GET_PRIVATE(object);
859         g_return_if_fail(priv);
860
861         LOC_COND_VOID(!priv->gps && !priv->wps, _E, "Error : Get property is not available now");
862
863         LOCATION_LOGW("Get Propery ID[%d]", property_id);
864
865         switch (property_id) {
866         case PROP_METHOD_TYPE:
867                 g_value_set_int(value, hybrid_get_current_method(priv));
868                 break;
869         case PROP_LAST_POSITION:
870                 g_value_set_boxed(value, priv->pos);
871                 break;
872         case PROP_BOUNDARY:
873                 g_value_set_pointer(value, g_list_first(priv->boundary_list));
874                 break;
875         case PROP_POS_INTERVAL:
876                 g_value_set_uint(value, priv->pos_interval);
877                 break;
878         case PROP_VEL_INTERVAL:
879                 g_value_set_uint(value, priv->vel_interval);
880                 break;
881         case PROP_SAT_INTERVAL:
882                 g_value_set_uint(value, priv->sat_interval);
883                 break;
884         case PROP_LOC_INTERVAL:
885                 g_value_set_uint(value, priv->loc_interval);
886                 break;
887         case PROP_MIN_INTERVAL:
888                 g_value_set_uint(value, priv->min_interval);
889                 break;
890         case PROP_MIN_DISTANCE:
891                 g_value_set_double(value, priv->min_distance);
892                 break;
893         case PROP_SERVICE_STATUS:
894                 g_value_set_int(value, priv->enabled);
895                 break;
896         default:
897                 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
898                 break;
899         }
900 }
901
902 static int
903 location_hybrid_get_position(LocationHybrid *self, LocationPosition **position, LocationAccuracy **accuracy)
904 {
905         LOC_FUNC_LOG
906         int ret = LOCATION_ERROR_NOT_AVAILABLE;
907         if (!location_setting_get_int(VCONFKEY_LOCATION_ENABLED) && !location_setting_get_int(VCONFKEY_LOCATION_NETWORK_ENABLED))
908                 return LOCATION_ERROR_SETTING_OFF;
909
910         LocationHybridPrivate *priv = GET_PRIVATE(self);
911         g_return_val_if_fail(priv, LOCATION_ERROR_NOT_AVAILABLE);
912
913         if (priv->pos) {
914                 *position = location_position_copy(priv->pos);
915                 ret = LOCATION_ERROR_NONE;
916         }
917
918         if (priv->acc)
919                 *accuracy = location_accuracy_copy(priv->acc);
920
921         return ret;
922 }
923
924 static int
925 location_hybrid_get_position_ext(LocationHybrid *self, LocationPosition **position, LocationVelocity **velocity, LocationAccuracy **accuracy)
926 {
927         LOC_FUNC_LOG
928         if (!location_setting_get_int(VCONFKEY_LOCATION_ENABLED) && !location_setting_get_int(VCONFKEY_LOCATION_NETWORK_ENABLED))
929                 return LOCATION_ERROR_SETTING_OFF;
930
931         LocationHybridPrivate *priv = GET_PRIVATE(self);
932         g_return_val_if_fail(priv, LOCATION_ERROR_NOT_AVAILABLE);
933
934         if (priv->pos && priv->vel) {
935                 *position = location_position_copy(priv->pos);
936                 *velocity = location_velocity_copy(priv->vel);
937         } else {
938                 LOCATION_LOGE("There is invalid data.");
939                 return LOCATION_ERROR_NOT_AVAILABLE;
940         }
941
942         if (priv->acc)
943                 *accuracy = location_accuracy_copy(priv->acc);
944         else
945                 *accuracy = location_accuracy_new(LOCATION_ACCURACY_LEVEL_NONE, 0.0, 0.0);
946
947         return LOCATION_ERROR_NONE;
948 }
949
950
951 static int
952 location_hybrid_get_last_position(LocationHybrid *self, LocationPosition **position, LocationAccuracy **accuracy)
953 {
954         LOC_FUNC_LOG
955
956         int ret = LOCATION_ERROR_NONE;
957         LocationPosition *gps_pos = NULL, *wps_pos = NULL;
958         LocationAccuracy *gps_acc = NULL, *wps_acc = NULL;
959         LocationHybridPrivate *priv = GET_PRIVATE(self);
960         g_return_val_if_fail(priv, LOCATION_ERROR_NOT_AVAILABLE);
961
962         if (priv->gps) location_get_last_position(priv->gps, &gps_pos, &gps_acc);
963         if (priv->wps) location_get_last_position(priv->wps, &wps_pos, &wps_acc);
964
965         if (gps_pos && wps_pos) {
966                 if (wps_pos->timestamp > gps_pos->timestamp) {
967                         *position = wps_pos;
968                         *accuracy = wps_acc;
969                         location_position_free(gps_pos);
970                         location_accuracy_free(gps_acc);
971                 } else {
972                         *position = gps_pos;
973                         *accuracy = gps_acc;
974                         location_position_free(wps_pos);
975                         location_accuracy_free(wps_acc);
976                 }
977         } else if (gps_pos) {
978                 *position = gps_pos;
979                 *accuracy = gps_acc;
980         } else if (wps_pos) {
981                 *position = wps_pos;
982                 *accuracy = wps_acc;
983         } else {
984                 ret = LOCATION_ERROR_NOT_AVAILABLE;
985         }
986
987         return ret;
988 }
989
990 static int
991 location_hybrid_get_last_position_ext(LocationHybrid *self, LocationPosition **position, LocationVelocity **velocity, LocationAccuracy **accuracy)
992 {
993         LOC_FUNC_LOG
994
995         int ret = LOCATION_ERROR_NONE;
996         LocationPosition *gps_pos = NULL, *wps_pos = NULL, *mock_pos = NULL;
997         LocationVelocity *gps_vel = NULL, *wps_vel = NULL, *mock_vel = NULL;
998         LocationAccuracy *gps_acc = NULL, *wps_acc = NULL, *mock_acc = NULL;
999         LocationHybridPrivate *priv = GET_PRIVATE(self);
1000         g_return_val_if_fail(priv, LOCATION_ERROR_NOT_AVAILABLE);
1001
1002         if (priv->gps) location_get_last_position_ext(priv->gps, &gps_pos, &gps_vel, &gps_acc);
1003         if (priv->wps) location_get_last_position_ext(priv->wps, &wps_pos, &wps_vel, &wps_acc);
1004         if (priv->mock) location_get_last_position_ext(priv->mock, &mock_pos, &mock_vel, &mock_acc);
1005
1006         if (gps_pos && wps_pos && gps_vel && wps_vel) {
1007                 if (mock_pos && mock_vel && mock_pos->timestamp > gps_pos->timestamp) {
1008                         *position = mock_pos;
1009                         *velocity = mock_vel;
1010                         *accuracy = mock_acc;
1011                         location_position_free(mock_pos);
1012                         location_velocity_free(mock_vel);
1013                         location_accuracy_free(mock_acc);
1014                 } else if (wps_pos->timestamp > gps_pos->timestamp) {
1015                         *position = wps_pos;
1016                         *velocity = wps_vel;
1017                         *accuracy = wps_acc;
1018                         location_position_free(gps_pos);
1019                         location_velocity_free(gps_vel);
1020                         location_accuracy_free(gps_acc);
1021                 } else {
1022                         *position = gps_pos;
1023                         *velocity = gps_vel;
1024                         *accuracy = gps_acc;
1025                         location_position_free(wps_pos);
1026                         location_velocity_free(wps_vel);
1027                         location_accuracy_free(wps_acc);
1028                 }
1029         } else if (gps_pos && gps_vel) {
1030                 *position = gps_pos;
1031                 *velocity = gps_vel;
1032                 *accuracy = gps_acc;
1033         } else if (wps_pos && wps_vel) {
1034                 *position = mock_pos;
1035                 *velocity = mock_vel;
1036                 *accuracy = mock_acc;
1037         } else {
1038                 ret = LOCATION_ERROR_NOT_AVAILABLE;
1039         }
1040
1041         return ret;
1042 }
1043
1044 static int
1045 location_hybrid_get_velocity(LocationHybrid *self, LocationVelocity **velocity, LocationAccuracy **accuracy)
1046 {
1047         LOC_FUNC_LOG
1048         int ret = LOCATION_ERROR_NOT_AVAILABLE;
1049         if (!location_setting_get_int(VCONFKEY_LOCATION_ENABLED) && !location_setting_get_int(VCONFKEY_LOCATION_NETWORK_ENABLED))
1050                 return LOCATION_ERROR_SETTING_OFF;
1051
1052         LocationHybridPrivate *priv = GET_PRIVATE(self);
1053         g_return_val_if_fail(priv, LOCATION_ERROR_NOT_AVAILABLE);
1054
1055         if (priv->vel) {
1056                 *velocity = location_velocity_copy(priv->vel);
1057                 ret = LOCATION_ERROR_NONE;
1058         }
1059
1060         if (priv->acc)
1061                 *accuracy = location_accuracy_copy(priv->acc);
1062
1063         return ret;
1064 }
1065
1066 static int
1067 location_hybrid_get_last_velocity(LocationHybrid *self, LocationVelocity **velocity, LocationAccuracy **accuracy)
1068 {
1069         LOC_FUNC_LOG
1070
1071         int ret = LOCATION_ERROR_NONE;
1072         LocationHybridPrivate *priv = GET_PRIVATE(self);
1073         g_return_val_if_fail(priv, LOCATION_ERROR_NOT_AVAILABLE);
1074         LocationVelocity *gps_vel = NULL, *wps_vel = NULL, *mock_vel = NULL;
1075         LocationAccuracy *gps_acc = NULL, *wps_acc = NULL, *mock_acc = NULL;
1076
1077         if (priv->gps) location_get_last_velocity(priv->gps, &gps_vel, &gps_acc);
1078         if (priv->wps) location_get_last_velocity(priv->wps, &wps_vel, &wps_acc);
1079         if (priv->mock) location_get_last_velocity(priv->mock, &mock_vel, &mock_acc);
1080
1081         if (gps_vel && wps_vel) {
1082                 if (mock_vel && mock_vel->timestamp > gps_vel->timestamp) {
1083                         *velocity = mock_vel;
1084                         *accuracy = mock_acc;
1085                         location_velocity_free(mock_vel);
1086                         location_accuracy_free(mock_acc);
1087                 } else if (wps_vel->timestamp > gps_vel->timestamp) {
1088                         *velocity = wps_vel;
1089                         *accuracy = wps_acc;
1090                         location_velocity_free(gps_vel);
1091                         location_accuracy_free(gps_acc);
1092                 } else {
1093                         *velocity = gps_vel;
1094                         *accuracy = gps_acc;
1095                         location_velocity_free(wps_vel);
1096                         location_accuracy_free(wps_acc);
1097                 }
1098         } else if (gps_vel) {
1099                 *velocity = gps_vel;
1100                 *accuracy = gps_acc;
1101         } else if (wps_vel) {
1102                 *velocity = wps_vel;
1103                 *accuracy = wps_acc;
1104         } else if (mock_vel) {
1105                 *velocity = mock_vel;
1106                 *accuracy = mock_acc;
1107         } else {
1108                 *velocity = NULL;
1109                 *accuracy = NULL;
1110                 ret = LOCATION_ERROR_NOT_AVAILABLE;
1111         }
1112
1113         return ret;
1114 }
1115
1116 static int
1117 location_hybrid_get_satellite(LocationHybrid *self, LocationSatellite **satellite)
1118 {
1119         LOC_FUNC_LOG
1120         int ret = LOCATION_ERROR_NOT_AVAILABLE;
1121         if (!location_setting_get_int(VCONFKEY_LOCATION_ENABLED) && !location_setting_get_int(VCONFKEY_LOCATION_NETWORK_ENABLED))
1122                 return LOCATION_ERROR_SETTING_OFF;
1123
1124         LocationHybridPrivate *priv = GET_PRIVATE(self);
1125         g_return_val_if_fail(priv, LOCATION_ERROR_NOT_AVAILABLE);
1126         if (priv->sat) {
1127                 *satellite = location_satellite_copy(priv->sat);
1128                 ret = LOCATION_ERROR_NONE;
1129         }
1130
1131         return ret;
1132 }
1133
1134 static int
1135 location_hybrid_get_last_satellite(LocationHybrid *self, LocationSatellite **satellite)
1136 {
1137         LOC_FUNC_LOG
1138
1139         int ret = LOCATION_ERROR_NONE;
1140         LocationHybridPrivate *priv = GET_PRIVATE(self);
1141         g_return_val_if_fail(priv, LOCATION_ERROR_NOT_AVAILABLE);
1142
1143         if (priv->gps) {
1144                 ret = location_get_last_satellite(priv->gps, satellite);
1145         } else {
1146                 *satellite = NULL;
1147                 ret = LOCATION_ERROR_NOT_AVAILABLE;
1148         }
1149
1150         return ret;
1151 }
1152
1153 static int
1154 location_hybrid_set_option(LocationHybrid *self, const char *option)
1155 {
1156         LOC_FUNC_LOG
1157         LocationHybridPrivate *priv = GET_PRIVATE(self);
1158         g_return_val_if_fail(priv, LOCATION_ERROR_NOT_AVAILABLE);
1159
1160         int ret_gps = LOCATION_ERROR_NOT_AVAILABLE;
1161         int ret_wps = LOCATION_ERROR_NOT_AVAILABLE;
1162
1163         if (priv->gps) ret_gps = location_set_option(priv->gps, option);
1164         if (priv->wps) ret_wps = location_set_option(priv->wps, option);
1165
1166         if (ret_gps != LOCATION_ERROR_NONE && ret_wps != LOCATION_ERROR_NONE)
1167                 return LOCATION_ERROR_NOT_AVAILABLE;
1168
1169         return LOCATION_ERROR_NONE;
1170 }
1171
1172 static int
1173 location_hybrid_request_single_location(LocationHybrid *self, int timeout)
1174 {
1175         LOC_FUNC_LOG
1176         LocationHybridPrivate *priv = GET_PRIVATE(self);
1177         g_return_val_if_fail(priv, LOCATION_ERROR_NOT_AVAILABLE);
1178
1179         int ret = LOCATION_ERROR_NOT_AVAILABLE;
1180
1181         if (priv->gps)
1182                 ret = location_request_single_location(priv->gps, timeout);
1183         else if (priv->wps)
1184                 ret = location_request_single_location(priv->wps, timeout);
1185         else if (priv->mock)
1186                 ret = location_request_single_location(priv->mock, timeout);
1187
1188         return ret;
1189 }
1190
1191 static int
1192 location_hybrid_get_nmea(LocationHybrid *self, char **nmea_data)
1193 {
1194         LOC_FUNC_LOG
1195         LocationHybridPrivate *priv = GET_PRIVATE(self);
1196         g_return_val_if_fail(priv, LOCATION_ERROR_NOT_AVAILABLE);
1197
1198         int ret = LOCATION_ERROR_NOT_AVAILABLE;
1199
1200         if (priv->gps) ret = location_get_nmea(priv->gps, nmea_data);
1201
1202         if (ret != LOCATION_ERROR_NONE)
1203                 return LOCATION_ERROR_NOT_AVAILABLE;
1204
1205         return LOCATION_ERROR_NONE;
1206 }
1207
1208 /*
1209  * Tizen 3.0
1210  */
1211 static int
1212 location_hybrid_set_mock_location(LocationMock *self, LocationPosition *position, LocationVelocity *velocity, LocationAccuracy *accuracy)
1213 {
1214         LocationHybridPrivate *priv = GET_PRIVATE(self);
1215         g_return_val_if_fail(priv, LOCATION_ERROR_NOT_AVAILABLE);
1216
1217         int ret = LOCATION_ERROR_NONE;
1218         LOC_COND_RET(!priv->mock, LOCATION_ERROR_NOT_AVAILABLE, _E, "MOCK Object is not created [%s]", err_msg(LOCATION_ERROR_NOT_AVAILABLE));
1219
1220         if (priv->mock)
1221                 ret = location_set_mock_location(priv->mock, position, velocity, accuracy);
1222
1223         LOC_IF_FAIL_LOG(ret, _E, "set_mock_location [%s]", err_msg(ret));
1224
1225         return ret;
1226 }
1227
1228 static int
1229 location_hybrid_clear_mock_location(LocationMock *self)
1230 {
1231         LocationHybridPrivate *priv = GET_PRIVATE(self);
1232         g_return_val_if_fail(priv, LOCATION_ERROR_NOT_AVAILABLE);
1233
1234         int ret = LOCATION_ERROR_NONE;
1235         LOC_COND_RET(!priv->mock, LOCATION_ERROR_NOT_AVAILABLE, _E, "MOCK Object is not created [%s]", err_msg(LOCATION_ERROR_NOT_AVAILABLE));
1236
1237         if (priv->mock)
1238                 ret = location_clear_mock_location(priv->mock);
1239
1240         LOC_IF_FAIL_LOG(ret, _E, "clear_mock_location [%s]", err_msg(ret));
1241
1242         return ret;
1243 }
1244
1245 static void
1246 location_ielement_interface_init(LocationIElementInterface *iface)
1247 {
1248         iface->start = (TYPE_START_FUNC)location_hybrid_start;
1249         iface->stop = (TYPE_STOP_FUNC)location_hybrid_stop;
1250         iface->get_position = (TYPE_GET_POSITION)location_hybrid_get_position;
1251         iface->get_position_ext = (TYPE_GET_POSITION_EXT)location_hybrid_get_position_ext;
1252         iface->get_last_position = (TYPE_GET_POSITION)location_hybrid_get_last_position;
1253         iface->get_last_position_ext = (TYPE_GET_POSITION_EXT)location_hybrid_get_last_position_ext;
1254         iface->get_velocity = (TYPE_GET_VELOCITY)location_hybrid_get_velocity;
1255         iface->get_last_velocity = (TYPE_GET_VELOCITY)location_hybrid_get_last_velocity;
1256         iface->get_satellite = (TYPE_GET_SATELLITE)location_hybrid_get_satellite;
1257         iface->get_last_satellite = (TYPE_GET_SATELLITE)location_hybrid_get_last_satellite;
1258         iface->set_option = (TYPE_SET_OPTION)location_hybrid_set_option;
1259         iface->request_single_location = (TYPE_REQUEST_SINGLE_LOCATION)location_hybrid_request_single_location;
1260         iface->get_nmea = (TYPE_GET_NMEA)location_hybrid_get_nmea;
1261
1262         iface->set_mock_location = (TYPE_SET_MOCK_LOCATION) location_hybrid_set_mock_location;
1263         iface->clear_mock_location = (TYPE_CLEAR_MOCK_LOCATION) location_hybrid_clear_mock_location;
1264 }
1265
1266 static void
1267 location_hybrid_init(LocationHybrid *self)
1268 {
1269         LOC_FUNC_LOG
1270         LocationHybridPrivate *priv = GET_PRIVATE(self);
1271         g_return_if_fail(priv);
1272
1273         priv->pos_interval = LOCATION_UPDATE_INTERVAL_NONE;
1274         priv->vel_interval = LOCATION_UPDATE_INTERVAL_NONE;
1275         priv->sat_interval = LOCATION_UPDATE_INTERVAL_NONE;
1276         priv->loc_interval = LOCATION_UPDATE_INTERVAL_NONE;
1277         priv->min_interval = LOCATION_UPDATE_INTERVAL_NONE;
1278
1279         priv->pos_updated_timestamp = 0;
1280         priv->vel_updated_timestamp = 0;
1281         priv->sat_updated_timestamp = 0;
1282         priv->loc_updated_timestamp = 0;
1283
1284         priv->gps_enabled = FALSE;
1285         priv->wps_enabled = FALSE;
1286         priv->gps = NULL;
1287         priv->wps = NULL;
1288
1289         priv->set_noti = FALSE;
1290         priv->signal_type = 0;
1291         priv->pos_timer = 0;
1292         priv->vel_timer = 0;
1293
1294         if (location_is_supported_method(LOCATION_METHOD_GPS)) priv->gps = location_new(LOCATION_METHOD_GPS);
1295         if (location_is_supported_method(LOCATION_METHOD_WPS)) priv->wps = location_new(LOCATION_METHOD_WPS);
1296         if (location_is_supported_method(LOCATION_METHOD_MOCK)) priv->mock = location_new(LOCATION_METHOD_MOCK);
1297
1298         if (priv->gps) {
1299                 g_signal_connect(priv->gps, "service-enabled", G_CALLBACK(hybrid_service_enabled), self);
1300                 g_signal_connect(priv->gps, "service-disabled", G_CALLBACK(hybrid_service_disabled), self);
1301                 /* g_signal_connect(priv->gps, "status-changed", G_CALLBACK(hybrid_status_changed), self); */
1302                 g_signal_connect(priv->gps, "service-updated", G_CALLBACK(hybrid_service_updated), self);
1303                 g_signal_connect(priv->gps, "location-updated", G_CALLBACK(hybrid_location_updated), self);
1304         }
1305         if (priv->wps) {
1306                 g_signal_connect(priv->wps, "service-enabled", G_CALLBACK(hybrid_service_enabled), self);
1307                 g_signal_connect(priv->wps, "service-disabled", G_CALLBACK(hybrid_service_disabled), self);
1308                 /* g_signal_connect(priv->wps, "status-changed", G_CALLBACK(hybrid_status_changed), self); */
1309                 g_signal_connect(priv->wps, "service-updated", G_CALLBACK(hybrid_service_updated), self);
1310                 g_signal_connect(priv->wps, "location-updated", G_CALLBACK(hybrid_location_updated), self);
1311         }
1312         if (priv->mock) {
1313                 g_signal_connect(priv->mock, "service-enabled", G_CALLBACK(hybrid_service_enabled), self);
1314                 g_signal_connect(priv->mock, "service-disabled", G_CALLBACK(hybrid_service_disabled), self);
1315                 /* g_signal_connect(priv->mock, "status-changed", G_CALLBACK(hybrid_status_changed), self); */
1316                 g_signal_connect(priv->mock, "service-updated", G_CALLBACK(hybrid_service_updated), self);
1317                 g_signal_connect(priv->mock, "location-updated", G_CALLBACK(hybrid_location_updated), self);
1318         }
1319
1320         hybrid_set_current_method(priv, LOCATION_TYPE_HYBRID);
1321         priv->enabled = FALSE;
1322
1323         priv->pos = NULL;
1324         priv->vel = NULL;
1325         priv->acc = NULL;
1326         priv->sat = NULL;
1327
1328         priv->boundary_list = NULL;
1329 }
1330
1331 static void
1332 location_hybrid_class_init(LocationHybridClass *klass)
1333 {
1334         LOC_FUNC_LOG
1335         GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
1336
1337         gobject_class->set_property = location_hybrid_set_property;
1338         gobject_class->get_property = location_hybrid_get_property;
1339
1340         gobject_class->dispose = location_hybrid_dispose;
1341         gobject_class->finalize = location_hybrid_finalize;
1342
1343         g_type_class_add_private(klass, sizeof(LocationHybridPrivate));
1344
1345         signals[SERVICE_ENABLED] = g_signal_new("service-enabled",
1346                                                                                         G_TYPE_FROM_CLASS(klass),
1347                                                                                         G_SIGNAL_RUN_FIRST |
1348                                                                                         G_SIGNAL_NO_RECURSE,
1349                                                                                         G_STRUCT_OFFSET(LocationHybridClass, enabled),
1350                                                                                         NULL, NULL,
1351                                                                                         location_VOID__UINT,
1352                                                                                         G_TYPE_NONE, 1,
1353                                                                                         G_TYPE_UINT);
1354
1355         signals[SERVICE_DISABLED] = g_signal_new("service-disabled",
1356                                                                                         G_TYPE_FROM_CLASS(klass),
1357                                                                                         G_SIGNAL_RUN_FIRST |
1358                                                                                         G_SIGNAL_NO_RECURSE,
1359                                                                                         G_STRUCT_OFFSET(LocationHybridClass, disabled),
1360                                                                                         NULL, NULL,
1361                                                                                         location_VOID__UINT,
1362                                                                                         G_TYPE_NONE, 1,
1363                                                                                         G_TYPE_UINT);
1364
1365 #if 0 /* TODO: STATUS_CHANGED will aggregate SERVICE_ENABLED and SERVICE_DISABLED */
1366         signals[STATUS_CHANGED] = g_signal_new("status-changed",
1367                                                                                         G_TYPE_FROM_CLASS(klass),
1368                                                                                         G_SIGNAL_RUN_FIRST |
1369                                                                                         G_SIGNAL_NO_RECURSE,
1370                                                                                         G_STRUCT_OFFSET(LocationHybridClass, status_changed),
1371                                                                                         NULL, NULL,
1372                                                                                         location_VOID__UINT,
1373                                                                                         G_TYPE_NONE, 1,
1374                                                                                         G_TYPE_UINT);
1375 #endif
1376
1377         signals[SERVICE_UPDATED] = g_signal_new("service-updated",
1378                                                                                         G_TYPE_FROM_CLASS(klass),
1379                                                                                         G_SIGNAL_RUN_FIRST |
1380                                                                                         G_SIGNAL_NO_RECURSE,
1381                                                                                         G_STRUCT_OFFSET(LocationHybridClass, service_updated),
1382                                                                                         NULL, NULL,
1383                                                                                         location_VOID__INT_POINTER_POINTER_POINTER,
1384                                                                                         G_TYPE_NONE, 4,
1385                                                                                         G_TYPE_INT,
1386                                                                                         G_TYPE_POINTER,
1387                                                                                         G_TYPE_POINTER,
1388                                                                                         G_TYPE_POINTER);
1389
1390         signals[LOCATION_UPDATED] = g_signal_new("location-updated",
1391                                                                                         G_TYPE_FROM_CLASS(klass),
1392                                                                                         G_SIGNAL_RUN_FIRST |
1393                                                                                         G_SIGNAL_NO_RECURSE,
1394                                                                                         G_STRUCT_OFFSET(LocationHybridClass, location_updated),
1395                                                                                         NULL, NULL,
1396                                                                                         location_VOID__INT_POINTER_POINTER_POINTER,
1397                                                                                         G_TYPE_NONE, 4,
1398                                                                                         G_TYPE_INT,
1399                                                                                         G_TYPE_POINTER,
1400                                                                                         G_TYPE_POINTER,
1401                                                                                         G_TYPE_POINTER);
1402
1403         signals[ZONE_IN] = g_signal_new("zone-in",
1404                                                                         G_TYPE_FROM_CLASS(klass),
1405                                                                         G_SIGNAL_RUN_FIRST |
1406                                                                         G_SIGNAL_NO_RECURSE,
1407                                                                         G_STRUCT_OFFSET(LocationHybridClass, zone_in),
1408                                                                         NULL, NULL,
1409                                                                         location_VOID__POINTER_POINTER_POINTER,
1410                                                                         G_TYPE_NONE, 3,
1411                                                                         G_TYPE_POINTER,
1412                                                                         G_TYPE_POINTER,
1413                                                                         G_TYPE_POINTER);
1414
1415         signals[ZONE_OUT] = g_signal_new("zone-out",
1416                                                                         G_TYPE_FROM_CLASS(klass),
1417                                                                         G_SIGNAL_RUN_FIRST |
1418                                                                         G_SIGNAL_NO_RECURSE,
1419                                                                         G_STRUCT_OFFSET(LocationHybridClass, zone_out),
1420                                                                         NULL, NULL,
1421                                                                         location_VOID__POINTER_POINTER_POINTER,
1422                                                                         G_TYPE_NONE, 3,
1423                                                                         G_TYPE_POINTER,
1424                                                                         G_TYPE_POINTER,
1425                                                                         G_TYPE_POINTER);
1426
1427         properties[PROP_METHOD_TYPE] = g_param_spec_int("method",
1428                                                                                                         "method type",
1429                                                                                                         "location method type name",
1430                                                                                                         LOCATION_METHOD_HYBRID,
1431                                                                                                         LOCATION_METHOD_HYBRID,
1432                                                                                                         LOCATION_METHOD_HYBRID,
1433                                                                                                         G_PARAM_READABLE);
1434
1435         properties[PROP_LAST_POSITION] = g_param_spec_boxed("last-position",
1436                                                                                                                 "hybrid last position prop",
1437                                                                                                                 "hybrid last position data",
1438                                                                                                                 LOCATION_TYPE_POSITION,
1439                                                                                                                 G_PARAM_READABLE);
1440
1441         properties[PROP_POS_INTERVAL] = g_param_spec_uint("pos-interval",
1442                                                                                                         "position interval prop",
1443                                                                                                         "position interval data",
1444                                                                                                         LOCATION_UPDATE_INTERVAL_MIN,
1445                                                                                                         LOCATION_UPDATE_INTERVAL_MAX,
1446                                                                                                         LOCATION_UPDATE_INTERVAL_DEFAULT,
1447                                                                                                         G_PARAM_READWRITE);
1448         properties[PROP_VEL_INTERVAL] = g_param_spec_uint("vel-interval",
1449                                                                                                         "velocity interval prop",
1450                                                                                                         "velocity interval data",
1451                                                                                                         LOCATION_UPDATE_INTERVAL_MIN,
1452                                                                                                         LOCATION_UPDATE_INTERVAL_MAX,
1453                                                                                                         LOCATION_UPDATE_INTERVAL_DEFAULT,
1454                                                                                                         G_PARAM_READWRITE);
1455         properties[PROP_SAT_INTERVAL] = g_param_spec_uint("sat-interval",
1456                                                                                                         "satellite interval prop",
1457                                                                                                         "satellite interval data",
1458                                                                                                         LOCATION_UPDATE_INTERVAL_MIN,
1459                                                                                                         LOCATION_UPDATE_INTERVAL_MAX,
1460                                                                                                         LOCATION_UPDATE_INTERVAL_DEFAULT,
1461                                                                                                         G_PARAM_READWRITE);
1462
1463         properties[PROP_LOC_INTERVAL] = g_param_spec_uint("loc-interval",
1464                                                                                                         "gps location interval prop",
1465                                                                                                         "gps location interval data",
1466                                                                                                         LOCATION_UPDATE_INTERVAL_MIN,
1467                                                                                                         LOCATION_UPDATE_INTERVAL_MAX,
1468                                                                                                         LOCATION_UPDATE_INTERVAL_DEFAULT,
1469                                                                                                         G_PARAM_READWRITE);
1470
1471         properties[PROP_MIN_INTERVAL] = g_param_spec_uint("min-interval",
1472                                                                                                         "gps distance-based interval prop",
1473                                                                                                         "gps distance-based interval data",
1474                                                                                                         LOCATION_MIN_INTERVAL_MIN,
1475                                                                                                         LOCATION_MIN_INTERVAL_MAX,
1476                                                                                                         LOCATION_MIN_INTERVAL_DEFAULT,
1477                                                                                                         G_PARAM_READWRITE);
1478
1479         properties[PROP_MIN_DISTANCE] = g_param_spec_double("min-distance",
1480                                                                                                                 "gps distance-based distance prop",
1481                                                                                                                 "gps distance-based distance data",
1482                                                                                                                 LOCATION_MIN_DISTANCE_MIN,
1483                                                                                                                 LOCATION_MIN_DISTANCE_MAX,
1484                                                                                                                 LOCATION_MIN_DISTANCE_DEFAULT,
1485                                                                                                                 G_PARAM_READWRITE);
1486
1487         properties[PROP_BOUNDARY] = g_param_spec_pointer("boundary",
1488                                                                                                         "hybrid boundary prop",
1489                                                                                                         "hybrid boundary data",
1490                                                                                                         G_PARAM_READWRITE);
1491
1492         properties[PROP_REMOVAL_BOUNDARY] = g_param_spec_boxed("removal-boundary",
1493                                                                                                                 "hybrid removal boundary prop",
1494                                                                                                                 "hybrid removal boundary data",
1495                                                                                                                 LOCATION_TYPE_BOUNDARY,
1496                                                                                                                 G_PARAM_READWRITE);
1497
1498         /* Tizen 3.0 */
1499         properties[PROP_SERVICE_STATUS] = g_param_spec_int("service-status",
1500                                                                                                         "location service status prop",
1501                                                                                                         "location service status data",
1502                                                                                                         LOCATION_STATUS_NO_FIX,
1503                                                                                                         LOCATION_STATUS_3D_FIX,
1504                                                                                                         LOCATION_STATUS_NO_FIX,
1505                                                                                                         G_PARAM_READABLE);
1506
1507         g_object_class_install_properties(gobject_class, PROP_MAX, properties);
1508 }