Release Tizen2.0 beta
[framework/api/location-manager.git] / src / locations.c
1 /*
2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License. 
15 */
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <locations_private.h>
21 #include <dlog.h>
22
23 #ifdef LOG_TAG
24 #undef LOG_TAG
25 #endif
26 #define LOG_TAG "TIZEN_N_LOCATION_MANAGER"
27
28 /*
29 * Internal Macros
30 */
31 #define LOCATIONS_CHECK_CONDITION(condition,error,msg)  \
32                 if(condition) {} else \
33                 { LOGE("[%s] %s(0x%08x)",__FUNCTION__, msg,error); return error;}; \
34
35 #define LOCATIONS_NULL_ARG_CHECK(arg)   \
36         LOCATIONS_CHECK_CONDITION(arg != NULL,LOCATIONS_ERROR_INVALID_PARAMETER,"LOCATIONS_ERROR_INVALID_PARAMETER") \
37
38 /*
39 * Internal Implementation
40 */
41
42 static int __convert_error_code(int code, char *func_name)
43 {
44         int ret;
45         char *msg = "LOCATIONS_ERROR_NONE";
46         switch (code) {
47         case LOCATION_ERROR_NONE:
48                 ret = LOCATIONS_ERROR_NONE;
49                 msg = "LOCATIONS_ERROR_NONE";
50                 break;
51         case LOCATION_ERROR_NETWORK_FAILED:
52         case LOCATION_ERROR_NETWORK_NOT_CONNECTED:
53                 ret = LOCATIONS_ERROR_NETWORK_FAILED;
54                 msg = "LOCATIONS_ERROR_NETWORK_FAILED";
55                 break;
56         case LOCATION_ERROR_NOT_ALLOWED:
57                 ret = LOCATIONS_ERROR_GPS_SETTING_OFF;
58                 msg = "LOCATIONS_ERROR_GPS_SETTING_OFF";
59                 break;
60         case LOCATION_ERROR_NOT_AVAILABLE:
61         case LOCATION_ERROR_CONFIGURATION:
62         case LOCATION_ERROR_PARAMETER:
63         case LOCATION_ERROR_UNKNOWN:
64         default:
65                 msg = "LOCATIONS_ERROR_SERVICE_NOT_AVAILABLE";
66                 ret = LOCATIONS_ERROR_SERVICE_NOT_AVAILABLE;
67         }
68         LOGE("[%s] %s(0x%08x) : core fw error(0x%x)", func_name, msg, ret, code);
69         return ret;
70 }
71
72 static void __cb_service_updated(GObject * self, guint type, gpointer data, gpointer accuracy, gpointer userdata)
73 {
74         LOGI("[%s] Callback function has been invoked. ", __FUNCTION__);
75         location_manager_s *handle = (location_manager_s *) userdata;
76         if (type == VELOCITY_UPDATED && handle->user_cb[_LOCATIONS_EVENT_TYPE_VELOCITY]) {
77                 LocationVelocity *vel = (LocationVelocity *) data;
78                 LOGI("[%s] Current velocity: timestamp : %d, speed: %f, direction : %f, climb : %f", __FUNCTION__,
79                      vel->timestamp, vel->speed, vel->direction, vel->climb);
80                 ((location_velocity_updated_cb) handle->user_cb[_LOCATIONS_EVENT_TYPE_VELOCITY]) (vel->speed, vel->direction,
81                                                                                                   vel->climb, vel->timestamp,
82                                                                                                   handle->user_data
83                                                                                                   [_LOCATIONS_EVENT_TYPE_VELOCITY]);
84         }
85         else if (type == POSITION_UPDATED && handle->user_cb[_LOCATIONS_EVENT_TYPE_POSITION]) {
86                 LocationPosition *pos = (LocationPosition *) data;
87                 LOGI("[%s] Current position: timestamp : %d, latitude : %f, altitude: %f, longitude: %f", __FUNCTION__,
88                      pos->timestamp, pos->latitude, pos->altitude, pos->longitude);
89                 ((location_position_updated_cb) handle->user_cb[_LOCATIONS_EVENT_TYPE_POSITION]) (pos->latitude, pos->longitude,
90                                                                                                   pos->altitude, pos->timestamp,
91                                                                                                   handle->user_data
92                                                                                                   [_LOCATIONS_EVENT_TYPE_POSITION]);
93         }
94         else if (type == SATELLITE_UPDATED && handle->user_cb[_LOCATIONS_EVENT_TYPE_SATELLITE]) {
95                 LocationSatellite *sat = (LocationSatellite *)data;
96                 LOGI("[%s] Current satellite information: timestamp : %d, number of active : %d, number of inview : %d", __FUNCTION__,
97                      sat->timestamp, sat->num_of_sat_used, sat->num_of_sat_inview);
98                 ((gps_status_satellite_updated_cb) handle->user_cb[_LOCATIONS_EVENT_TYPE_SATELLITE]) (sat->num_of_sat_used, sat->num_of_sat_inview,
99                                                                                                  sat->timestamp, handle->user_data[_LOCATIONS_EVENT_TYPE_SATELLITE]);
100         }
101 }
102
103 static void __cb_service_enabled(GObject * self, guint status, gpointer userdata)
104 {
105         LOGI("[%s] Callback function has been invoked. ", __FUNCTION__);
106         location_manager_s *handle = (location_manager_s *) userdata;
107         if (handle->user_cb[_LOCATIONS_EVENT_TYPE_SERVICE_STATE]) {
108                 ((location_service_state_changed_cb)
109                  handle->user_cb[_LOCATIONS_EVENT_TYPE_SERVICE_STATE]) (LOCATIONS_SERVICE_ENABLED,
110                                                                         handle->user_data[_LOCATIONS_EVENT_TYPE_SERVICE_STATE]);
111         }
112 }
113
114 static void __cb_service_disabled(GObject * self, guint status, gpointer userdata)
115 {
116         LOGI("[%s] Callback function has been invoked. ", __FUNCTION__);
117         location_manager_s *handle = (location_manager_s *) userdata;
118         if (handle->user_cb[_LOCATIONS_EVENT_TYPE_SERVICE_STATE])
119                 ((location_service_state_changed_cb)
120                  handle->user_cb[_LOCATIONS_EVENT_TYPE_SERVICE_STATE]) (LOCATIONS_SERVICE_DISABLED,
121                                                                         handle->user_data[_LOCATIONS_EVENT_TYPE_SERVICE_STATE]);
122 }
123
124 static void __cb_zone_in(GObject * self, guint type, gpointer position, gpointer accuracy, gpointer userdata)
125 {
126         location_manager_s *handle = (location_manager_s *) userdata;
127         if (handle->user_cb[_LOCATIONS_EVENT_TYPE_BOUNDARY]) {
128                 LocationPosition *pos = (LocationPosition *) position;
129                 ((location_zone_changed_cb) handle->user_cb[_LOCATIONS_EVENT_TYPE_BOUNDARY]) (LOCATIONS_BOUNDARY_IN,
130                                                                                               pos->latitude, pos->longitude,
131                                                                                               pos->altitude, pos->timestamp,
132                                                                                               handle->user_data
133                                                                                               [_LOCATIONS_EVENT_TYPE_BOUNDARY]);
134         }
135 }
136
137 static void __cb_zone_out(GObject * self, guint type, gpointer position, gpointer accuracy, gpointer userdata)
138 {
139         location_manager_s *handle = (location_manager_s *) userdata;
140         if (handle->user_cb[_LOCATIONS_EVENT_TYPE_BOUNDARY]) {
141                 LocationPosition *pos = (LocationPosition *) position;
142                 ((location_zone_changed_cb) handle->user_cb[_LOCATIONS_EVENT_TYPE_BOUNDARY]) (LOCATIONS_BOUNDARY_OUT,
143                                                                                               pos->latitude, pos->longitude,
144                                                                                               pos->altitude, pos->timestamp,
145                                                                                               handle->user_data
146                                                                                               [_LOCATIONS_EVENT_TYPE_BOUNDARY]);
147         }
148 }
149
150 static int __set_callback(_location_event_e type, location_manager_h manager, void *callback, void *user_data)
151 {
152         LOCATIONS_NULL_ARG_CHECK(manager);
153         LOCATIONS_NULL_ARG_CHECK(callback);
154         location_manager_s *handle = (location_manager_s *) manager;
155         handle->user_cb[type] = callback;
156         handle->user_data[type] = user_data;
157         LOGI("[%s] event type : %d. ", __FUNCTION__, type);
158         return LOCATIONS_ERROR_NONE;
159 }
160
161 static int __unset_callback(_location_event_e type, location_manager_h manager)
162 {
163         LOCATIONS_NULL_ARG_CHECK(manager);
164         location_manager_s *handle = (location_manager_s *) manager;
165         handle->user_cb[type] = NULL;
166         handle->user_data[type] = NULL;
167         LOGI("[%s] event type : %d. ", __FUNCTION__, type);
168         return LOCATIONS_ERROR_NONE;
169 }
170
171 static void __foreach_boundary(LocationBoundary * boundary, void *user_data)
172 {
173         location_manager_s *handle = (location_manager_s *) user_data;
174
175         if (handle != NULL && boundary != NULL) {
176                 int ret = -1;
177                 location_bounds_h bounds;
178                 if (boundary->type == LOCATION_BOUNDARY_CIRCLE) {
179                         location_coords_s center;
180                         center.latitude = boundary->circle.center->latitude;
181                         center.longitude = boundary->circle.center->longitude;
182                         ret = location_bounds_create_circle(center, boundary->circle.radius, &bounds);
183                 } else if (boundary->type == LOCATION_BOUNDARY_RECT) {
184                         location_coords_s left_top;
185                         location_coords_s right_bottom;
186                         left_top.latitude = boundary->rect.left_top->latitude;
187                         left_top.longitude = boundary->rect.left_top->longitude;
188                         right_bottom.latitude = boundary->rect.right_bottom->latitude;
189                         right_bottom.longitude = boundary->rect.right_bottom->longitude;
190                         ret = location_bounds_create_rect(left_top, right_bottom, &bounds);
191                 } else if (boundary->type == LOCATION_BOUNDARY_POLYGON) {
192                         GList *list = boundary->polygon.position_list;
193                         int size = g_list_length(list);
194                         if (size > 0) {
195                                 location_coords_s coords[size];
196                                 int cnt = 0;
197                                 while (list) {
198                                         LocationPosition *pos = list->data;
199                                         coords[cnt].latitude = pos->latitude;
200                                         coords[cnt].longitude = pos->longitude;
201                                         list = g_list_next(list);
202                                         cnt++;
203                                 }
204                                 ret = location_bounds_create_polygon(coords, size, &bounds);
205                         }
206                 } else {
207                         LOGI("[%s] Invalid boundary type : %d", __FUNCTION__, boundary->type);
208                 }
209
210                 if (ret != LOCATIONS_ERROR_NONE) {
211                         LOGI("[%s] Failed to create location_bounds : (0x%08x) ", __FUNCTION__, ret);
212                 } else {
213                         if (handle->is_continue_foreach_bounds) {
214                                 handle->is_continue_foreach_bounds =
215                                     ((location_bounds_cb) handle->user_cb[_LOCATIONS_EVENT_TYPE_FOREACH_BOUNDS]) (bounds,
216                                                                                                                   handle->
217                                                                                                                   user_data
218                                                                                                                   [_LOCATIONS_EVENT_TYPE_FOREACH_BOUNDS]);
219                         }
220                         location_bounds_destroy(bounds);
221                 }
222         } else {
223                 LOGI("[%s]  __foreach_boundary() has been failed", __FUNCTION__);
224         }
225 }
226
227 /////////////////////////////////////////
228 // Location Manager
229 ////////////////////////////////////////
230
231 /*
232 * Public Implementation
233 */
234
235 bool location_manager_is_supported_method(location_method_e method)
236 {
237         LocationMethod _method = LOCATION_METHOD_NONE;
238         switch (method) {
239         case LOCATIONS_METHOD_HYBRID:
240                 _method = LOCATION_METHOD_HYBRID;
241                 break;
242         case LOCATIONS_METHOD_GPS:
243                 _method = LOCATION_METHOD_GPS;
244                 break;
245         case LOCATIONS_METHOD_WPS:
246                 _method = LOCATION_METHOD_WPS;
247                 break;
248         case LOCATIONS_METHOD_CPS:
249                 _method = LOCATION_METHOD_CPS;
250                 break;
251         default:
252                 _method = LOCATION_METHOD_NONE;
253                 break;
254         }
255         return location_is_supported_method(_method);
256 }
257
258 int location_manager_create(location_method_e method, location_manager_h * manager)
259 {
260         LOCATIONS_NULL_ARG_CHECK(manager);
261         if (location_init() != LOCATION_ERROR_NONE)
262                 return LOCATIONS_ERROR_SERVICE_NOT_AVAILABLE;
263
264         LocationMethod _method = LOCATION_METHOD_NONE;
265         switch (method) {
266         case LOCATIONS_METHOD_HYBRID:
267                 _method = LOCATION_METHOD_HYBRID;
268                 break;
269         case LOCATIONS_METHOD_GPS:
270                 _method = LOCATION_METHOD_GPS;
271                 break;
272         case LOCATIONS_METHOD_WPS:
273                 _method = LOCATION_METHOD_WPS;
274                 break;
275         case LOCATIONS_METHOD_CPS:
276                 _method = LOCATION_METHOD_CPS;
277                 break;
278         case LOCATIONS_METHOD_NONE:
279                 return LOCATIONS_ERROR_SERVICE_NOT_AVAILABLE;
280         default:
281                 {
282                         LOGE("[%s] LOCATIONS_ERROR_INVALID_PARAMETER(0x%08x) : Out of range (location_method_e) - method : %d ",
283                              __FUNCTION__, LOCATIONS_ERROR_INVALID_PARAMETER, method);
284                         return LOCATIONS_ERROR_INVALID_PARAMETER;
285                 }
286         }
287
288         location_manager_s *handle = (location_manager_s *) malloc(sizeof(location_manager_s));
289         if (handle == NULL) {
290                 LOGE("[%s] OUT_OF_MEMORY(0x%08x)", __FUNCTION__, LOCATIONS_ERROR_OUT_OF_MEMORY);
291                 return LOCATIONS_ERROR_OUT_OF_MEMORY;
292         }
293
294         memset(handle, 0, sizeof(location_manager_s));
295
296         handle->object = location_new(_method);
297         if (handle->object == NULL) {
298                 LOGE("[%s] LOCATIONS_ERROR_SERVICE_NOT_AVAILABLE(0x%08x) : fail to location_new", __FUNCTION__,
299                      LOCATIONS_ERROR_SERVICE_NOT_AVAILABLE);
300                 free(handle);
301                 return LOCATIONS_ERROR_SERVICE_NOT_AVAILABLE;
302         }
303         handle->method = method;
304         handle->is_continue_foreach_bounds = TRUE;
305         *manager = (location_manager_h) handle;
306         return LOCATIONS_ERROR_NONE;
307 }
308
309 int location_manager_destroy(location_manager_h manager)
310 {
311         LOCATIONS_NULL_ARG_CHECK(manager);
312         location_manager_s *handle = (location_manager_s *) manager;
313
314         int ret = location_free(handle->object);
315         if (ret != LOCATIONS_ERROR_NONE) {
316                 return __convert_error_code(ret, (char *)__FUNCTION__);
317         }
318         free(handle);
319         return LOCATIONS_ERROR_NONE;
320 }
321
322 int location_manager_start(location_manager_h manager)
323 {
324         LOCATIONS_NULL_ARG_CHECK(manager);
325         location_manager_s *handle = (location_manager_s *) manager;
326
327         g_signal_connect(handle->object, "service-enabled", G_CALLBACK(__cb_service_enabled), handle);
328         g_signal_connect(handle->object, "service-disabled", G_CALLBACK(__cb_service_disabled), handle);
329         g_signal_connect(handle->object, "service-updated", G_CALLBACK(__cb_service_updated), handle);
330         g_signal_connect(handle->object, "zone-in", G_CALLBACK(__cb_zone_in), handle);
331         g_signal_connect(handle->object, "zone-out", G_CALLBACK(__cb_zone_out), handle);
332
333         int ret = location_start(handle->object);
334         if (ret != LOCATION_ERROR_NONE) {
335                 return __convert_error_code(ret, (char *)__FUNCTION__);
336         }
337         return LOCATIONS_ERROR_NONE;
338 }
339
340 int location_manager_stop(location_manager_h manager)
341 {
342         LOCATIONS_NULL_ARG_CHECK(manager);
343         location_manager_s *handle = (location_manager_s *) manager;
344
345         int ret = location_stop(handle->object);
346         if (ret != LOCATION_ERROR_NONE) {
347                 return __convert_error_code(ret, (char *)__FUNCTION__);
348         }
349         return LOCATIONS_ERROR_NONE;
350 }
351
352 int location_manager_add_boundary(location_manager_h manager, const location_bounds_h bounds)
353 {
354         LOCATIONS_NULL_ARG_CHECK(manager);
355         LOCATIONS_NULL_ARG_CHECK(bounds);
356
357         location_manager_s *handle = (location_manager_s *) manager;
358         int ret = location_boundary_add(handle->object,(LocationBoundary*)bounds);
359
360         if (ret != LOCATION_ERROR_NONE) {
361                 return __convert_error_code(ret, (char *)__FUNCTION__);
362         }
363         return LOCATIONS_ERROR_NONE;
364 }
365
366 int location_manager_remove_boundary(location_manager_h manager, const location_bounds_h bounds)
367 {
368         LOCATIONS_NULL_ARG_CHECK(manager);
369         LOCATIONS_NULL_ARG_CHECK(bounds);
370
371         location_manager_s *handle = (location_manager_s *) manager;
372         int ret = location_boundary_remove(handle->object, (LocationBoundary*)bounds);
373
374         if (ret != LOCATION_ERROR_NONE) {
375                 return __convert_error_code(ret, (char *)__FUNCTION__);
376         }
377         return LOCATIONS_ERROR_NONE;
378 }
379
380 int location_manager_foreach_boundary(location_manager_h manager, location_bounds_cb callback, void *user_data)
381 {
382         LOCATIONS_NULL_ARG_CHECK(manager);
383         LOCATIONS_NULL_ARG_CHECK(callback);
384
385         location_manager_s *handle = (location_manager_s *) manager;
386         handle->user_cb[_LOCATIONS_EVENT_TYPE_FOREACH_BOUNDS] = callback;
387         handle->user_data[_LOCATIONS_EVENT_TYPE_FOREACH_BOUNDS] = user_data;
388         handle->is_continue_foreach_bounds = TRUE;
389         int ret = location_boundary_foreach(handle->object, __foreach_boundary, handle);
390         if (ret != LOCATION_ERROR_NONE) {
391                 return __convert_error_code(ret, (char *)__FUNCTION__);
392         }
393         return LOCATIONS_ERROR_NONE;
394 }
395
396 int location_manager_get_method(location_manager_h manager, location_method_e * method)
397 {
398         LOCATIONS_NULL_ARG_CHECK(manager);
399         LOCATIONS_NULL_ARG_CHECK(method);
400         location_manager_s *handle = (location_manager_s *) manager;
401         LocationMethod _method = LOCATION_METHOD_NONE;
402         g_object_get(handle->object, "method", &_method, NULL);
403         switch (_method) {
404         case LOCATION_METHOD_NONE:
405                 *method = LOCATIONS_METHOD_NONE;
406                 break;
407         case LOCATION_METHOD_HYBRID:
408                 *method = LOCATIONS_METHOD_HYBRID;
409                 break;
410         case LOCATION_METHOD_GPS:
411                 *method = LOCATIONS_METHOD_GPS;
412                 break;
413         case LOCATION_METHOD_WPS:
414                 *method = LOCATIONS_METHOD_WPS;
415                 break;
416         case LOCATION_METHOD_CPS:
417                 *method = LOCATIONS_METHOD_CPS;
418                 break;
419         default:
420                 {
421                         LOGE("[%s] LOCATIONS_ERROR_INVALID_PARAMETER(0x%08x) : Out of range (location_method_e) - method : %d ",
422                              __FUNCTION__, LOCATIONS_ERROR_INVALID_PARAMETER, method);
423                         return LOCATIONS_ERROR_INVALID_PARAMETER;
424                 }
425         }
426         //*method = handle->method;
427         return LOCATIONS_ERROR_NONE;
428 }
429
430 int location_manager_get_position(location_manager_h manager, double *altitude, double *latitude, double *longitude,
431                                   time_t * timestamp)
432 {
433         LOCATIONS_NULL_ARG_CHECK(manager);
434         LOCATIONS_NULL_ARG_CHECK(altitude);
435         LOCATIONS_NULL_ARG_CHECK(latitude);
436         LOCATIONS_NULL_ARG_CHECK(longitude);
437         LOCATIONS_NULL_ARG_CHECK(timestamp);
438
439         location_manager_s *handle = (location_manager_s *) manager;
440         int ret;
441         LocationPosition *pos = NULL;
442         LocationAccuracy *acc = NULL;
443         ret = location_get_position(handle->object, &pos, &acc);
444         if (ret != LOCATION_ERROR_NONE) {
445                 return __convert_error_code(ret, (char *)__FUNCTION__);
446         }
447
448         if (pos->status == LOCATION_STATUS_NO_FIX) {
449                 *altitude = -1;
450                 *latitude = -1;
451                 *longitude = -1;
452         } else {
453                 if (pos->status == LOCATION_STATUS_3D_FIX) {
454                         *altitude = pos->altitude;
455                 } else {
456                         *altitude = -1;
457                 }
458                 *latitude = pos->latitude;
459                 *longitude = pos->longitude;
460         }
461         *timestamp = pos->timestamp;
462         location_position_free(pos);
463         location_accuracy_free(acc);
464         return LOCATIONS_ERROR_NONE;
465 }
466
467 int location_manager_get_velocity(location_manager_h manager, double *climb, double *direction, double *speed, time_t * timestamp)
468 {
469         LOCATIONS_NULL_ARG_CHECK(manager);
470         LOCATIONS_NULL_ARG_CHECK(climb);
471         LOCATIONS_NULL_ARG_CHECK(direction);
472         LOCATIONS_NULL_ARG_CHECK(speed);
473         LOCATIONS_NULL_ARG_CHECK(timestamp);
474
475         location_manager_s *handle = (location_manager_s *) manager;
476         int ret;
477         LocationVelocity *vel = NULL;
478         LocationAccuracy *acc = NULL;
479         ret = location_get_velocity(handle->object, &vel, &acc);
480         if (ret != LOCATION_ERROR_NONE) {
481                 return __convert_error_code(ret, (char *)__FUNCTION__);
482         }
483
484         *climb = vel->climb;
485         *direction = vel->direction;
486         *speed = vel->speed;
487         *timestamp = vel->timestamp;
488         location_velocity_free(vel);
489         location_accuracy_free(acc);
490         return LOCATIONS_ERROR_NONE;
491 }
492
493 int location_manager_get_accuracy(location_manager_h manager, location_accuracy_level_e * level, double *horizontal,
494                                   double *vertical)
495 {
496         LOCATIONS_NULL_ARG_CHECK(manager);
497         LOCATIONS_NULL_ARG_CHECK(level);
498         LOCATIONS_NULL_ARG_CHECK(horizontal);
499         LOCATIONS_NULL_ARG_CHECK(vertical);
500         location_manager_s *handle = (location_manager_s *) manager;
501
502         int ret;
503         LocationPosition *pos = NULL;
504         LocationAccuracy *acc = NULL;
505         ret = location_get_position(handle->object, &pos, &acc);
506         if (ret != LOCATION_ERROR_NONE) {
507                 return __convert_error_code(ret, (char *)__FUNCTION__);
508         }
509
510         *level = acc->level;
511         *horizontal = acc->horizontal_accuracy;
512         *vertical = acc->vertical_accuracy;
513         location_position_free(pos);
514         location_accuracy_free(acc);
515         return LOCATIONS_ERROR_NONE;
516 }
517
518 int location_manager_get_last_position(location_manager_h manager, double *altitude, double *latitude, double *longitude,
519                                        time_t * timestamp)
520 {
521         LOCATIONS_NULL_ARG_CHECK(manager);
522         LOCATIONS_NULL_ARG_CHECK(altitude);
523         LOCATIONS_NULL_ARG_CHECK(latitude);
524         LOCATIONS_NULL_ARG_CHECK(longitude);
525         LOCATIONS_NULL_ARG_CHECK(timestamp);
526
527         location_manager_s *handle = (location_manager_s *) manager;
528
529         int ret;
530         LocationPosition *last_pos = NULL;
531         LocationAccuracy *last_acc = NULL;
532         ret = location_get_last_position(handle->object, &last_pos, &last_acc);
533         if (ret != LOCATION_ERROR_NONE) {
534                 return __convert_error_code(ret, (char *)__FUNCTION__);
535         }
536
537         if (last_pos->status == LOCATION_STATUS_NO_FIX) {
538                 *altitude = -1;
539                 *latitude = -1;
540                 *longitude = -1;
541         } else {
542                 if (last_pos->status == LOCATION_STATUS_3D_FIX) {
543                         *altitude = last_pos->altitude;
544                 } else {
545                         *altitude = -1;
546                 }
547                 *latitude = last_pos->latitude;
548                 *longitude = last_pos->longitude;
549         }
550         *timestamp = last_pos->timestamp;
551         location_position_free(last_pos);
552         location_accuracy_free(last_acc);
553         return LOCATIONS_ERROR_NONE;
554 }
555
556 int location_manager_get_last_velocity(location_manager_h manager, double *climb, double *direction, double *speed, time_t * timestamp)
557 {
558         LOCATIONS_NULL_ARG_CHECK(manager);
559         LOCATIONS_NULL_ARG_CHECK(climb);
560         LOCATIONS_NULL_ARG_CHECK(direction);
561         LOCATIONS_NULL_ARG_CHECK(speed);
562         LOCATIONS_NULL_ARG_CHECK(timestamp);
563
564         location_manager_s *handle = (location_manager_s *) manager;
565
566         int ret;
567         LocationVelocity *last_vel = NULL;
568         LocationAccuracy *last_acc = NULL;
569         ret = location_get_last_velocity(handle->object, &last_vel, &last_acc);
570         if (ret != LOCATION_ERROR_NONE) {
571                 return __convert_error_code(ret, (char *)__FUNCTION__);
572         }
573
574         *climb = last_vel->climb;
575         *direction = last_vel->direction;
576         *speed = last_vel->speed;
577         *timestamp = last_vel->timestamp;
578         location_velocity_free(last_vel);
579         location_accuracy_free(last_acc);
580         return LOCATIONS_ERROR_NONE;
581 }
582
583 int location_manager_get_last_accuracy(location_manager_h manager, location_accuracy_level_e * level, double *horizontal,
584                                        double *vertical)
585 {
586         LOCATIONS_NULL_ARG_CHECK(manager);
587         LOCATIONS_NULL_ARG_CHECK(level);
588         LOCATIONS_NULL_ARG_CHECK(horizontal);
589         LOCATIONS_NULL_ARG_CHECK(vertical);
590         location_manager_s *handle = (location_manager_s *) manager;
591
592         int ret;
593         LocationPosition *last_pos = NULL;
594         LocationAccuracy *last_acc = NULL;
595         ret = location_get_last_position(handle->object, &last_pos, &last_acc);
596         if (ret != LOCATION_ERROR_NONE) {
597                 return __convert_error_code(ret, (char *)__FUNCTION__);
598         }
599
600         *level = last_acc->level;
601         *horizontal = last_acc->horizontal_accuracy;
602         *vertical = last_acc->vertical_accuracy;
603         location_position_free(last_pos);
604         location_accuracy_free(last_acc);
605         return LOCATIONS_ERROR_NONE;
606 }
607
608 int location_manager_set_position_updated_cb(location_manager_h manager, location_position_updated_cb callback, int interval, void *user_data)
609 {
610         LOCATIONS_CHECK_CONDITION(interval >= 1
611                                   && interval <= 120, LOCATIONS_ERROR_INVALID_PARAMETER, "LOCATIONS_ERROR_INVALID_PARAMETER");
612         LOCATIONS_NULL_ARG_CHECK(manager);
613         location_manager_s *handle = (location_manager_s *) manager;
614         g_object_set(handle->object, "pos-interval", interval, NULL);
615         return __set_callback(_LOCATIONS_EVENT_TYPE_POSITION, manager, callback, user_data);
616 }
617
618 int location_manager_unset_position_updated_cb(location_manager_h manager)
619 {
620         return __unset_callback(_LOCATIONS_EVENT_TYPE_POSITION, manager);
621 }
622
623 int location_manager_set_velocity_updated_cb(location_manager_h manager, location_velocity_updated_cb callback, int interval, void *user_data)
624 {
625         LOCATIONS_CHECK_CONDITION(interval >= 1
626                                   && interval <= 120, LOCATIONS_ERROR_INVALID_PARAMETER, "LOCATIONS_ERROR_INVALID_PARAMETER");
627         LOCATIONS_NULL_ARG_CHECK(manager);
628         location_manager_s *handle = (location_manager_s *) manager;
629         g_object_set(handle->object, "vel-interval", interval, NULL);
630         return __set_callback(_LOCATIONS_EVENT_TYPE_VELOCITY, manager, callback, user_data);
631 }
632
633 int location_manager_unset_velocity_updated_cb(location_manager_h manager)
634 {
635         return __unset_callback(_LOCATIONS_EVENT_TYPE_VELOCITY, manager);
636 }
637
638 int location_manager_set_service_state_changed_cb(location_manager_h manager, location_service_state_changed_cb callback,
639                                                   void *user_data)
640 {
641         return __set_callback(_LOCATIONS_EVENT_TYPE_SERVICE_STATE, manager, callback, user_data);
642 }
643
644 int location_manager_unset_service_state_changed_cb(location_manager_h manager)
645 {
646         return __unset_callback(_LOCATIONS_EVENT_TYPE_SERVICE_STATE, manager);
647 }
648
649 int location_manager_set_zone_changed_cb(location_manager_h manager, location_zone_changed_cb callback, void *user_data)
650 {
651         return __set_callback(_LOCATIONS_EVENT_TYPE_BOUNDARY, manager, callback, user_data);
652 }
653
654 int location_manager_unset_zone_changed_cb(location_manager_h manager)
655 {
656         return __unset_callback(_LOCATIONS_EVENT_TYPE_BOUNDARY, manager);
657 }
658
659 int location_manager_get_distance(double start_latitude, double start_longitude, double end_latitude, double end_longitude, double *distance)
660 {
661         LOCATIONS_NULL_ARG_CHECK(distance);
662         LOCATIONS_CHECK_CONDITION(start_latitude>=-90 && start_latitude<=90,LOCATION_BOUNDS_ERROR_INVALID_PARAMETER,"LOCATION_BOUNDS_ERROR_INVALID_PARAMETER");
663         LOCATIONS_CHECK_CONDITION(start_longitude>=-180 && start_longitude<=180,LOCATION_BOUNDS_ERROR_INVALID_PARAMETER, "LOCATION_BOUNDS_ERROR_INVALID_PARAMETER");
664         LOCATIONS_CHECK_CONDITION(end_latitude>=-90 && end_latitude<=90,LOCATION_BOUNDS_ERROR_INVALID_PARAMETER, "LOCATION_BOUNDS_ERROR_INVALID_PARAMETER");
665         LOCATIONS_CHECK_CONDITION(end_longitude>=-180 && end_longitude<=180,LOCATION_BOUNDS_ERROR_INVALID_PARAMETER, "LOCATION_BOUNDS_ERROR_INVALID_PARAMETER");
666
667         int ret = LOCATION_ERROR_NONE;
668         ulong u_distance;
669
670         LocationPosition *start = location_position_new (0, start_latitude, start_longitude, 0, LOCATION_STATUS_2D_FIX);
671         LocationPosition *end = location_position_new (0, end_latitude, end_longitude, 0, LOCATION_STATUS_2D_FIX);
672
673         ret = location_get_distance (start, end, &u_distance);
674         if (ret != LOCATION_ERROR_NONE) {
675                 return __convert_error_code(ret, (char *)__FUNCTION__);
676         }
677
678         *distance = (double)u_distance;
679
680         return LOCATIONS_ERROR_NONE;
681 }
682
683 int location_manager_send_command(const char *cmd)
684 {
685         LOCATIONS_NULL_ARG_CHECK(cmd);
686
687         int ret;
688         ret = location_send_command(cmd);
689         if (ret != LOCATION_ERROR_NONE) {
690                 return __convert_error_code(ret, (char *)__FUNCTION__);
691         }
692
693         return LOCATIONS_ERROR_NONE;
694 }
695
696 /////////////////////////////////////////
697 // GPS Status & Satellites
698 ////////////////////////////////////////
699
700 int gps_status_get_nmea(location_manager_h manager, char **nmea)
701 {
702         LOCATIONS_NULL_ARG_CHECK(manager);
703         LOCATIONS_NULL_ARG_CHECK(nmea);
704         location_manager_s *handle = (location_manager_s *) manager;
705
706         if (handle->method == LOCATIONS_METHOD_HYBRID) {
707                 LocationMethod _method = LOCATION_METHOD_NONE;
708                 g_object_get(handle->object, "method", &_method, NULL);
709                 if (_method != LOCATION_METHOD_GPS) {
710                         LOGE("[%s] LOCATIONS_ERROR_INCORRECT_METHOD(0x%08x) : method - %d", __FUNCTION__,
711                              LOCATIONS_ERROR_INCORRECT_METHOD, handle->method);
712                         return LOCATIONS_ERROR_INCORRECT_METHOD;
713                 }
714         } else if (handle->method != LOCATIONS_METHOD_GPS) {
715                 LOGE("[%s] LOCATIONS_ERROR_INCORRECT_METHOD(0x%08x) : method - %d", __FUNCTION__,
716                      LOCATIONS_ERROR_INCORRECT_METHOD, handle->method);
717                 return LOCATIONS_ERROR_INCORRECT_METHOD;
718         }
719         gchar *nmea_data = NULL;
720         g_object_get(handle->object, "nmea", &nmea_data, NULL);
721         if (nmea_data == NULL) {
722                 LOGE("[%s] LOCATIONS_ERROR_SERVICE_NOT_AVAILABLE(0x%08x) : nmea data is NULL ", __FUNCTION__,
723                      LOCATIONS_ERROR_SERVICE_NOT_AVAILABLE);
724                 return LOCATIONS_ERROR_SERVICE_NOT_AVAILABLE;
725         }
726         *nmea = NULL;
727         *nmea = strdup(nmea_data);
728         if (*nmea == NULL) {
729                 LOGE("[%s] LOCATIONS_ERROR_OUT_OF_MEMORY(0x%08x) : fail to strdup ", __FUNCTION__,
730                      LOCATIONS_ERROR_OUT_OF_MEMORY);
731                 return LOCATIONS_ERROR_OUT_OF_MEMORY;
732         }
733         g_free(nmea_data);
734         return LOCATIONS_ERROR_NONE;
735 }
736
737 int gps_status_get_satellite(location_manager_h manager, int *num_of_active, int *num_of_inview, time_t *timestamp)
738 {
739         LOCATIONS_NULL_ARG_CHECK(manager);
740         LOCATIONS_NULL_ARG_CHECK(num_of_active);
741         LOCATIONS_NULL_ARG_CHECK(num_of_inview);
742         LOCATIONS_NULL_ARG_CHECK(timestamp);
743         location_manager_s *handle = (location_manager_s *) manager;
744         LocationSatellite *sat = NULL;
745         int ret = location_get_satellite (handle->object, &sat);
746         if (ret != LOCATION_ERROR_NONE || sat == NULL) {
747                 if (ret == LOCATION_ERROR_NOT_SUPPORTED) {
748                         LOGE("[%s] LOCATIONS_ERROR_INCORRECT_METHOD(0x%08x) : method - %d", __FUNCTION__,
749                              LOCATIONS_ERROR_INCORRECT_METHOD, handle->method);
750                         return LOCATIONS_ERROR_INCORRECT_METHOD;
751                 }
752
753                 LOGE("[%s] LOCATIONS_ERROR_SERVICE_NOT_AVAILABLE(0x%08x) : satellite is NULL ", __FUNCTION__,
754                      LOCATIONS_ERROR_SERVICE_NOT_AVAILABLE);
755                 return LOCATIONS_ERROR_SERVICE_NOT_AVAILABLE;
756         }
757
758         *num_of_active = sat->num_of_sat_used;
759         *num_of_inview = sat->num_of_sat_inview;
760         *timestamp = sat->timestamp;
761         location_satellite_free(sat);
762         sat = NULL;
763         return LOCATIONS_ERROR_NONE;
764 }
765
766 int gps_status_set_satellite_updated_cb(location_manager_h manager, gps_status_satellite_updated_cb callback, int interval, void *user_data)
767 {
768         LOCATIONS_CHECK_CONDITION(interval >= 1
769                                   && interval <= 120, LOCATIONS_ERROR_INVALID_PARAMETER, "LOCATIONS_ERROR_INVALID_PARAMETER");
770         LOCATIONS_NULL_ARG_CHECK(manager);
771         location_manager_s *handle = (location_manager_s *) manager;
772         g_object_set(handle->object, "sat-interval", interval, NULL);
773         return __set_callback(_LOCATIONS_EVENT_TYPE_SATELLITE, manager, callback, user_data);
774 }
775
776 int gps_status_unset_satellite_updated_cb(location_manager_h manager)
777 {
778         return __unset_callback(_LOCATIONS_EVENT_TYPE_SATELLITE, manager);
779 }
780
781
782 int gps_status_foreach_satellites_in_view(location_manager_h manager, gps_status_get_satellites_cb callback, void *user_data)
783 {
784         LOCATIONS_NULL_ARG_CHECK(manager);
785         LOCATIONS_NULL_ARG_CHECK(callback);
786         location_manager_s *handle = (location_manager_s *) manager;
787         LocationSatellite *sat = NULL;
788         int ret = location_get_satellite (handle->object, &sat);
789         if (ret != LOCATION_ERROR_NONE || sat == NULL) {
790                 if (ret == LOCATION_ERROR_NOT_SUPPORTED) {
791                         LOGE("[%s] LOCATIONS_ERROR_INCORRECT_METHOD(0x%08x) : method - %d", __FUNCTION__,
792                              LOCATIONS_ERROR_INCORRECT_METHOD, handle->method);
793                         return LOCATIONS_ERROR_INCORRECT_METHOD;
794                 }
795
796                 LOGE("[%s] LOCATIONS_ERROR_SERVICE_NOT_AVAILABLE(0x%08x) : satellite is NULL ", __FUNCTION__,
797                      LOCATIONS_ERROR_SERVICE_NOT_AVAILABLE);
798                 return LOCATIONS_ERROR_SERVICE_NOT_AVAILABLE;
799         }
800
801         int i;
802         for (i = 0; i < sat->num_of_sat_inview; i++) {
803                 guint prn;
804                 gboolean used;
805                 guint elevation;
806                 guint azimuth;
807                 gint snr;
808                 location_satellite_get_satellite_details(sat, i, &prn, &used, &elevation, &azimuth, &snr);
809                 if (callback(azimuth, elevation, prn, snr, used, user_data) != TRUE)
810                         break;
811         }
812         location_satellite_free(sat);
813         sat = NULL;
814         return LOCATIONS_ERROR_NONE;
815 }
816
817 int gps_status_get_last_satellite(location_manager_h manager, int *num_of_active, int *num_of_inview, time_t *timestamp)
818 {
819         LOCATIONS_NULL_ARG_CHECK(manager);
820         LOCATIONS_NULL_ARG_CHECK(num_of_active);
821         LOCATIONS_NULL_ARG_CHECK(num_of_inview);
822         LOCATIONS_NULL_ARG_CHECK(timestamp);
823         location_manager_s *handle = (location_manager_s *) manager;
824         int ret = LOCATION_ERROR_NONE;
825         LocationSatellite *last_sat = NULL;
826         ret = location_get_last_satellite(handle->object, &last_sat);
827         if (ret != LOCATION_ERROR_NONE || last_sat == NULL) {
828                 if (ret == LOCATION_ERROR_NOT_SUPPORTED) {
829                         LOGE("[%s] LOCATIONS_ERROR_INCORRECT_METHOD(0x%08x) : method - %d", __FUNCTION__,
830                              LOCATIONS_ERROR_INCORRECT_METHOD, handle->method);
831                         return LOCATIONS_ERROR_INCORRECT_METHOD;
832                 }
833
834                 LOGE("[%s] LOCATIONS_ERROR_SERVICE_NOT_AVAILABLE(0x%08x) : satellite is NULL ", __FUNCTION__,
835                      LOCATIONS_ERROR_SERVICE_NOT_AVAILABLE);
836                 return LOCATIONS_ERROR_SERVICE_NOT_AVAILABLE;
837         }
838
839         *num_of_active = last_sat->num_of_sat_used;
840         *num_of_inview = last_sat->num_of_sat_inview;
841         *timestamp = last_sat->timestamp;
842         location_satellite_free(last_sat);
843         return LOCATIONS_ERROR_NONE;
844 }
845
846 int gps_status_foreach_last_satellites_in_view(location_manager_h manager, gps_status_get_satellites_cb callback,
847                                                void *user_data)
848 {
849         LOCATIONS_NULL_ARG_CHECK(manager);
850         LOCATIONS_NULL_ARG_CHECK(callback);
851         location_manager_s *handle = (location_manager_s *) manager;
852         int ret;
853         LocationSatellite *last_sat = NULL;
854         ret = location_get_last_satellite(handle->object, &last_sat);
855         if (ret != LOCATION_ERROR_NONE || last_sat == NULL) {
856                 if (ret == LOCATION_ERROR_NOT_SUPPORTED) {
857                         LOGE("[%s] LOCATIONS_ERROR_INCORRECT_METHOD(0x%08x) : method - %d", __FUNCTION__,
858                              LOCATIONS_ERROR_INCORRECT_METHOD, handle->method);
859                         return LOCATIONS_ERROR_INCORRECT_METHOD;
860                 }
861
862                 LOGE("[%s] LOCATIONS_ERROR_SERVICE_NOT_AVAILABLE(0x%08x) : satellite is NULL ", __FUNCTION__,
863                      LOCATIONS_ERROR_SERVICE_NOT_AVAILABLE);
864                 return LOCATIONS_ERROR_SERVICE_NOT_AVAILABLE;
865         }
866
867         int i;
868         for (i = 0; i < last_sat->num_of_sat_inview; i++) {
869                 guint prn;
870                 gboolean used;
871                 guint elevation;
872                 guint azimuth;
873                 gint snr;
874                 location_satellite_get_satellite_details(last_sat, i, &prn, &used, &elevation, &azimuth, &snr);
875                 if (callback(azimuth, elevation, prn, snr, used, user_data) != TRUE) {
876                         break;
877                 }
878         }
879         location_satellite_free(last_sat);
880         return LOCATIONS_ERROR_NONE;
881 }