Fixed SVACE defects.
[platform/core/location/lbs-server.git] / lbs-server / src / lbs_server.c
1 /*
2  * lbs-server
3  *
4  * Copyright (c) 2011-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 #include <stdio.h>
23 #include <string.h>
24 #include <time.h>
25 #include <stdlib.h>
26 #include <glib.h>
27 #include <glib-object.h>
28
29 #include <vconf.h>
30 #include "setting.h"
31 #include <lbs_dbus_server.h>
32
33 #include "gps_plugin_data_types.h"
34 #include "lbs_server.h"
35
36 #include "nps_plugin_module.h"
37 #include "nps_plugin_intf.h"
38
39 #include "server.h"
40 #include "last_position.h"
41 #include "debug_util.h"
42 #include "dump_log.h"
43
44
45 typedef struct {
46         /* gps variables */
47         pos_data_t position;
48         batch_data_t batch;
49         sv_data_t satellite;
50         nmea_data_t nmea;
51         gboolean sv_used;
52         gboolean nmea_used;
53
54         gboolean is_gps_running;
55         gint gps_client_count;
56
57         /* nps variables */
58         NpsManagerHandle handle;
59         unsigned long period;
60         NpsManagerPositionExt pos;
61         NpsManagerLastPositionExt last_pos;
62         Plugin_LocationInfo location;
63
64         gboolean is_nps_running;
65         gint nps_client_count;
66         unsigned char *token;
67
68         /* shared variables */
69         GMainLoop *loop;
70         GMutex mutex;
71         GCond cond;
72         LbsStatus status;
73
74         /* dynamic interval update */
75         GHashTable *dynamic_interval_table;
76         guint *optimized_interval_array;
77         guint temp_minimum_interval;
78         gboolean is_needed_changing_interval;
79
80         lbs_server_dbus_h lbs_dbus_server;
81 } lbs_server_s;
82
83 typedef struct {
84         lbs_server_s *lbs_server;
85         int method;
86 } dynamic_interval_updator_user_data;
87
88 static gboolean gps_remove_all_clients(lbs_server_s *lbs_server);
89
90 static void __setting_gps_cb(keynode_t *key, gpointer user_data)
91 {
92         LOG_GPS(DBG_LOW, "ENTER >>>");
93         lbs_server_s *lbs_server = (lbs_server_s *)user_data;
94         int onoff = 0;
95         gboolean ret = FALSE;
96
97         setting_get_int(VCONFKEY_LOCATION_ENABLED, &onoff);
98
99         if (onoff == 0) {
100                 ret = gps_remove_all_clients(lbs_server);
101                 if (ret == FALSE) {
102                         LOG_GPS(DBG_LOW, "already removed.");
103                 }
104         }
105 }
106
107 static void nps_set_last_position(NpsManagerPositionExt pos)
108 {
109         LOG_NPS(DBG_LOW, "nps_set_last_position[%d]", pos.timestamp);
110
111         char location[128] = {0,};
112         snprintf(location, sizeof(location), "%.6lf;%.6lf;%.2lf;%.2lf;%.2lf;%.2lf;", pos.latitude, pos.longitude, pos.altitude, pos.speed, pos.direction, pos.hor_accuracy);
113
114         setting_set_int(VCONFKEY_LOCATION_NV_LAST_WPS_TIMESTAMP, pos.timestamp);
115         setting_set_string(VCONFKEY_LOCATION_NV_LAST_WPS_LOCATION, location);
116 }
117
118 static void nps_set_position(lbs_server_s *lbs_server_nps, NpsManagerPositionExt pos)
119 {
120         LOG_NPS(DBG_LOW, "set position timestamp : %d", pos.timestamp);
121         lbs_server_nps->last_pos.timestamp = pos.timestamp;
122         setting_set_int(VCONFKEY_LOCATION_LAST_WPS_TIMESTAMP, lbs_server_nps->last_pos.timestamp);
123
124         if ((lbs_server_nps->last_pos.latitude != pos.latitude) || (lbs_server_nps->last_pos.longitude != pos.longitude)) {
125                 lbs_server_nps->last_pos.latitude = pos.latitude;
126                 lbs_server_nps->last_pos.longitude = pos.longitude;
127                 lbs_server_nps->last_pos.altitude = pos.altitude;
128                 lbs_server_nps->last_pos.hor_accuracy = pos.hor_accuracy;
129                 lbs_server_nps->last_pos.speed = pos.speed;
130                 lbs_server_nps->last_pos.direction = pos.direction;
131
132                 setting_set_double(VCONFKEY_LOCATION_LAST_WPS_LATITUDE, lbs_server_nps->last_pos.latitude);
133                 setting_set_double(VCONFKEY_LOCATION_LAST_WPS_LONGITUDE, lbs_server_nps->last_pos.longitude);
134                 setting_set_double(VCONFKEY_LOCATION_LAST_WPS_ALTITUDE, lbs_server_nps->last_pos.altitude);
135                 setting_set_double(VCONFKEY_LOCATION_LAST_WPS_SPEED, lbs_server_nps->last_pos.speed);
136                 setting_set_double(VCONFKEY_LOCATION_LAST_WPS_DIRECTION, lbs_server_nps->last_pos.direction);
137                 setting_set_double(VCONFKEY_LOCATION_LAST_WPS_HOR_ACCURACY, lbs_server_nps->last_pos.hor_accuracy);
138         }
139
140         int last_timestamp = 0;
141         setting_get_int(VCONFKEY_LOCATION_NV_LAST_WPS_TIMESTAMP, &last_timestamp);
142
143         LOG_NPS(DBG_LOW, "last_time stamp: %d, pos.timestamp: %d, UPDATE_INTERVAL: %d ", last_timestamp, pos.timestamp, UPDATE_INTERVAL);
144         if ((pos.timestamp - last_timestamp) > UPDATE_INTERVAL) {
145                 nps_set_last_position(pos);
146         }
147
148 }
149
150 static void nps_set_status(lbs_server_s *lbs_server, LbsStatus status)
151 {
152         if (!lbs_server) {
153                 LOG_NPS(DBG_ERR, "lbs_server is NULL!!");
154                 return;
155         }
156         LOG_NPS(DBG_LOW, "nps_set_status[%d]", status);
157         if (lbs_server->status == status) {
158                 LOG_NPS(DBG_ERR, "Donot update NPS status");
159                 return;
160         }
161
162         lbs_server->status = status;
163
164         if (lbs_server->status == LBS_STATUS_AVAILABLE) {
165                 setting_set_int(VCONFKEY_LOCATION_WPS_STATE, POSITION_CONNECTED);
166         } else if (lbs_server->status == LBS_STATUS_ACQUIRING) {
167                 setting_set_int(VCONFKEY_LOCATION_WPS_STATE, POSITION_SEARCHING);
168         } else {
169                 setting_set_int(VCONFKEY_LOCATION_WPS_STATE, POSITION_OFF);
170         }
171
172         if (status != LBS_STATUS_AVAILABLE) {
173                 lbs_server->pos.fields = LBS_POSITION_FIELDS_NONE;
174         }
175
176         lbs_server_emit_status_changed(lbs_server->lbs_dbus_server, LBS_SERVER_METHOD_NPS, status);
177 }
178
179 static void nps_update_position(lbs_server_s *lbs_server_nps, NpsManagerPositionExt pos)
180 {
181         if (!lbs_server_nps) {
182                 LOG_NPS(DBG_ERR, "lbs-server is NULL!!");
183                 return;
184         }
185
186         GVariant *accuracy = NULL;
187
188         LOG_NPS(DBG_LOW, "nps_update_position");
189         lbs_server_nps->pos.fields = pos.fields;
190         lbs_server_nps->pos.timestamp = pos.timestamp;
191         lbs_server_nps->pos.latitude = pos.latitude;
192         lbs_server_nps->pos.longitude = pos.longitude;
193         lbs_server_nps->pos.altitude = pos.altitude;
194         lbs_server_nps->pos.hor_accuracy = pos.hor_accuracy;
195         lbs_server_nps->pos.ver_accuracy = pos.ver_accuracy;
196
197         accuracy = g_variant_ref_sink(g_variant_new("(idd)", lbs_server_nps->pos.acc_level, lbs_server_nps->pos.hor_accuracy, lbs_server_nps->pos.ver_accuracy));
198
199         LOG_NPS(DBG_LOW, "time:%d", lbs_server_nps->pos.timestamp);
200
201         lbs_server_emit_position_changed(lbs_server_nps->lbs_dbus_server, LBS_SERVER_METHOD_NPS,
202                                                                         lbs_server_nps->pos.fields, lbs_server_nps->pos.timestamp, lbs_server_nps->pos.latitude,
203                                                                         lbs_server_nps->pos.longitude, lbs_server_nps->pos.altitude, lbs_server_nps->pos.speed,
204                                                                         lbs_server_nps->pos.direction, 0.0, accuracy);
205
206         g_variant_unref(accuracy);
207 }
208
209 static gboolean nps_report_callback(gpointer user_data)
210 {
211         LOG_NPS(DBG_LOW, "ENTER >>>");
212         double  vertical_accuracy = -1.0; /* vertical accuracy's invalid value is -1 */
213         Plugin_LocationInfo location;
214         memset(&location, 0x00, sizeof(Plugin_LocationInfo));
215         lbs_server_s *lbs_server_nps = (lbs_server_s *) user_data;
216         if (NULL == lbs_server_nps) {
217                 LOG_GPS(DBG_ERR, "lbs_server_s is NULL!!");
218                 return FALSE;
219         }
220         time_t timestamp;
221
222         g_mutex_lock(&lbs_server_nps->mutex);
223         memcpy(&location, &lbs_server_nps->location, sizeof(Plugin_LocationInfo));
224         g_mutex_unlock(&lbs_server_nps->mutex);
225
226         time(&timestamp);
227         if (timestamp == lbs_server_nps->last_pos.timestamp) {
228                 return FALSE;
229         }
230
231         nps_set_status(lbs_server_nps, LBS_STATUS_AVAILABLE);
232
233         NpsManagerPositionExt pos;
234         memset(&pos, 0x00, sizeof(NpsManagerPositionExt));
235
236         pos.timestamp = timestamp;
237
238         if (location.latitude) {
239                 pos.fields |= LBS_POSITION_EXT_FIELDS_LATITUDE;
240                 pos.latitude = location.latitude;
241         }
242
243         if (location.longitude) {
244                 pos.fields |= LBS_POSITION_EXT_FIELDS_LONGITUDE;
245                 pos.longitude = location.longitude;
246         }
247
248         if (location.altitude) {
249                 pos.fields |= LBS_POSITION_EXT_FIELDS_ALTITUDE;
250                 pos.altitude = location.altitude;
251         }
252
253         if (location.speed >= 0) {
254                 pos.fields |= LBS_POSITION_EXT_FIELDS_SPEED;
255                 pos.speed = location.speed;
256         }
257         if (location.bearing >= 0) {
258                 pos.fields |= LBS_POSITION_EXT_FIELDS_DIRECTION;
259                 pos.direction = location.bearing;
260         }
261
262         pos.acc_level = LBS_ACCURACY_LEVEL_STREET;
263         pos.hor_accuracy = location.hpe;
264         pos.ver_accuracy = vertical_accuracy;
265
266         nps_update_position(lbs_server_nps, pos);
267
268         nps_set_position(lbs_server_nps, pos);
269
270         return FALSE;
271 }
272
273 static void __nps_callback(void *arg, const Plugin_LocationInfo *location, const void *reserved)
274 {
275         LOG_NPS(DBG_LOW, "ENTER >>>");
276         lbs_server_s *lbs_server = (lbs_server_s *)arg;
277         if (!lbs_server) {
278                 LOG_NPS(DBG_ERR, "lbs_server is NULL!!");
279                 return;
280         }
281
282         if (!location) {
283                 LOG_NPS(DBG_LOW, "NULL is returned from plugin...");
284                 /* sometimes plugin returns NULL even if it is connected... */
285                 /*nps_set_status (lbs_server , LBS_STATUS_ACQUIRING); */
286                 return;
287         }
288
289         g_mutex_lock(&lbs_server->mutex);
290         memcpy(&lbs_server->location, location, sizeof(Plugin_LocationInfo));
291         g_mutex_unlock(&lbs_server->mutex);
292
293         g_main_context_invoke(NULL, nps_report_callback, arg);
294 }
295
296 static void _nps_token_callback(void *arg, const unsigned char *token, unsigned tokenSize)
297 {
298         LOG_NPS(DBG_LOW, "ENTER >>>");
299         lbs_server_s *lbs_server_nps = (lbs_server_s *)arg;
300         if (NULL == lbs_server_nps) {
301                 LOG_NPS(DBG_ERR, "lbs-server is NULL!!");
302                 return;
303         }
304
305         if (token == NULL) {
306                 LOG_NPS(DBG_ERR, "*** no token to save\n");
307         } else {
308                 /* save the token in persistent storage */
309                 g_mutex_lock(&lbs_server_nps->mutex);
310                 lbs_server_nps->token = g_new0(unsigned char, tokenSize);
311                 if (lbs_server_nps->token) {
312                         memcpy(lbs_server_nps->token, token, tokenSize);
313                 }
314                 g_mutex_unlock(&lbs_server_nps->mutex);
315         }
316         LOG_NPS(DBG_LOW, "_nps_token_callback ended");
317 }
318
319 static void _network_enabled_cb(keynode_t *key, void *user_data)
320 {
321         LOG_GPS(DBG_LOW, "ENTER >>>");
322         int enabled = 0;
323
324         setting_get_int(VCONFKEY_LOCATION_NETWORK_ENABLED, &enabled);
325
326         /* This is vestige of nps-server
327         lbs_server_s *lbs_server_nps = (lbs_server_s *)user_data;
328
329         if (enabled == 0) {
330                 if (lbs_server_nps->loop != NULL) {
331                         g_main_loop_quit(lbs_server_nps->loop);
332                 }
333         }
334         */
335 }
336 static gboolean nps_offline_location(lbs_server_s *lbs_server)
337 {
338         LOG_NPS(DBG_LOW, "ENTER >>>");
339         if (NULL == lbs_server) {
340                 LOG_GPS(DBG_ERR, "lbs-server is NULL!!");
341                 return FALSE;
342         }
343         char key[NPS_UNIQUE_ID_LEN] = { 0, };
344
345         if (setting_get_unique_id(key)) {
346                 LOG_NPS(DBG_LOW, "key = %s", key);
347                 get_nps_plugin_module()->getOfflineToken((unsigned char *)key, NPS_UNIQUE_ID_LEN,
348                                 _nps_token_callback, lbs_server);
349                 if (lbs_server->token != NULL) {
350                         LOG_NPS(DBG_LOW, "Token = %s", lbs_server->token);
351                         int ret = get_nps_plugin_module()->offlineLocation((unsigned char *)key,
352                                         NPS_UNIQUE_ID_LEN, lbs_server->token, 0,
353                                         __nps_callback, lbs_server);
354                         if (ret) {
355                                 if (lbs_server->is_nps_running) {
356                                         LOG_NPS(DBG_LOW, "offlineLocation() called nps_callback successfully.");
357                                         return TRUE;
358                                 }
359                         }
360                 } else {
361                         LOG_NPS(DBG_ERR, "getOfflineToken(): Token is NULL");
362                 }
363         } else {
364                 LOG_NPS(DBG_ERR, "lbs_get_unique_id() failed.");
365         }
366         return TRUE;
367 }
368
369 static void __nps_cancel_callback(void *arg)
370 {
371         LOG_NPS(DBG_LOW, "__nps_cancel_callback");
372         lbs_server_s *lbs_server = (lbs_server_s *) arg;
373         if (!lbs_server) {
374                 LOG_NPS(DBG_ERR, "lbs-server is NULL!!");
375                 return;
376         }
377
378         g_mutex_lock(&lbs_server->mutex);
379         lbs_server->is_nps_running = FALSE;
380         g_cond_signal(&lbs_server->cond);
381         g_mutex_unlock(&lbs_server->mutex);
382 }
383
384 static void start_batch_tracking(lbs_server_s *lbs_server, int batch_interval, int batch_period)
385 {
386         g_mutex_lock(&lbs_server->mutex);
387         lbs_server->gps_client_count++;
388         g_mutex_unlock(&lbs_server->mutex);
389
390         if (lbs_server->is_gps_running == TRUE) {
391                 LOG_GPS(DBG_LOW, "Batch: gps is already running");
392                 return;
393         }
394         LOG_GPS(DBG_LOW, "Batch: start_tracking GPS");
395         lbs_server->status = LBS_STATUS_ACQUIRING;
396
397         if (request_start_batch_session(batch_interval, batch_period) == TRUE) {
398                 g_mutex_lock(&lbs_server->mutex);
399                 lbs_server->is_gps_running = TRUE;
400                 g_mutex_unlock(&lbs_server->mutex);
401
402                 lbs_server->is_needed_changing_interval = FALSE;
403
404                 /* ADD notify */
405                 setting_notify_key_changed(VCONFKEY_LOCATION_ENABLED, __setting_gps_cb, lbs_server);
406         } else {
407                 LOG_GPS(DBG_ERR, "Batch: Fail to request_start_batch_session");
408         }
409 }
410
411 static void stop_batch_tracking(lbs_server_s *lbs_server)
412 {
413         LOG_GPS(DBG_LOW, "ENTER >>>");
414
415         g_mutex_lock(&lbs_server->mutex);
416         lbs_server->gps_client_count--;
417         g_mutex_unlock(&lbs_server->mutex);
418
419         if (lbs_server->is_gps_running == FALSE) {
420                 LOG_GPS(DBG_LOW, "Batch: gps- is already stopped");
421                 return;
422         }
423
424         if (lbs_server->gps_client_count <= 0) {
425                 g_mutex_lock(&lbs_server->mutex);
426                 lbs_server->gps_client_count = 0;
427
428                 if (request_stop_batch_session() == TRUE) {
429                         lbs_server->is_gps_running = FALSE;
430                         lbs_server->sv_used = FALSE;
431                         /* remove notify */
432                         setting_ignore_key_changed(VCONFKEY_LOCATION_ENABLED, __setting_gps_cb);
433                         g_mutex_unlock(&lbs_server->mutex);
434                 }
435         }
436
437         lbs_server->status = LBS_STATUS_UNAVAILABLE;
438         lbs_server_emit_status_changed(lbs_server->lbs_dbus_server, LBS_SERVER_METHOD_GPS, LBS_STATUS_UNAVAILABLE);
439 }
440
441 static void start_tracking(lbs_server_s *lbs_server, lbs_server_method_e method)
442 {
443         switch (method) {
444                 case LBS_SERVER_METHOD_GPS:
445
446                         g_mutex_lock(&lbs_server->mutex);
447                         lbs_server->gps_client_count++;
448                         g_mutex_unlock(&lbs_server->mutex);
449
450                         if (lbs_server->is_gps_running == TRUE) {
451                                 LOG_GPS(DBG_LOW, "gps is already running");
452                                 return;
453                         }
454                         LOG_GPS(DBG_LOW, "start_tracking GPS");
455                         lbs_server->status = LBS_STATUS_ACQUIRING;
456
457                         if (request_start_session((int)(lbs_server->optimized_interval_array[method])) == TRUE) {
458                                 g_mutex_lock(&lbs_server->mutex);
459                                 lbs_server->is_gps_running = TRUE;
460                                 g_mutex_unlock(&lbs_server->mutex);
461
462                                 lbs_server->is_needed_changing_interval = FALSE;
463
464                                 /* ADD notify */
465                                 setting_notify_key_changed(VCONFKEY_LOCATION_ENABLED, __setting_gps_cb, lbs_server);
466                         } else {
467                                 LOG_GPS(DBG_ERR, "Fail to request_start_session");
468                         }
469
470                         break;
471
472                 case LBS_SERVER_METHOD_NPS:
473                         g_mutex_lock(&lbs_server->mutex);
474                         lbs_server->nps_client_count++;
475                         g_mutex_unlock(&lbs_server->mutex);
476
477                         if (lbs_server->is_nps_running == TRUE) {
478                                 LOG_NPS(DBG_LOW, "nps is already running");
479                                 return;
480                         }
481
482                         LOG_NPS(DBG_LOW, "start_tracking - LBS_SERVER_METHOD_NPS");
483                         nps_set_status(lbs_server, LBS_STATUS_ACQUIRING);
484
485                         void *handle_str = NULL;
486                         int ret = get_nps_plugin_module()->start(lbs_server->period, __nps_callback, lbs_server, &(handle_str));
487                         LOG_NPS(DBG_LOW, "after get_nps_plugin_module()->location");
488
489                         if (ret) {
490                                 lbs_server->handle = handle_str;
491                                 g_mutex_lock(&lbs_server->mutex);
492                                 lbs_server->is_nps_running = TRUE;
493                                 g_mutex_unlock(&lbs_server->mutex);
494                                 vconf_ignore_key_changed(VCONFKEY_LOCATION_NETWORK_ENABLED, _network_enabled_cb);
495                                 return;
496                         }
497
498                         if (nps_is_dummy_plugin_module() != TRUE) {
499                                 nps_offline_location(lbs_server);
500                         }
501
502                         LOG_NPS(DBG_ERR, "FAILS WPS START");
503                         nps_set_status(lbs_server, LBS_STATUS_ERROR);
504                         break;
505
506                 default:
507                         LOG_GPS(DBG_LOW, "start_tracking Invalid");
508         }
509
510 }
511
512 static gboolean nps_stop(lbs_server_s *lbs_server_nps)
513 {
514         LOG_NPS(DBG_LOW, "ENTER >>>");
515         if (!lbs_server_nps) {
516                 LOG_NPS(DBG_ERR, "lbs-server is NULL!!");
517                 return FALSE;
518         }
519
520         int ret = get_nps_plugin_module()->stop(lbs_server_nps->handle, __nps_cancel_callback, lbs_server_nps);
521         if (ret) {
522                 g_mutex_lock(&lbs_server_nps->mutex);
523                 while (lbs_server_nps->is_nps_running) {
524                         g_cond_wait(&lbs_server_nps->cond, &lbs_server_nps->mutex);
525                 }
526                 lbs_server_nps->is_nps_running = FALSE;
527                 g_mutex_unlock(&lbs_server_nps->mutex);
528         }
529         /* This is vestige of nps-server
530         else {
531                 if (lbs_server_nps->loop != NULL) {
532                         LOG_NPS(DBG_ERR, "module->stop() is failed. nps is cloesed.");
533                         g_main_loop_quit(lbs_server_nps->loop);
534                         return FALSE;
535                 }
536         }
537         */
538
539         nps_set_status(lbs_server_nps, LBS_STATUS_UNAVAILABLE);
540
541         return TRUE;
542 }
543
544 static void stop_tracking(lbs_server_s *lbs_server, lbs_server_method_e method)
545 {
546         switch (method) {
547                 case LBS_SERVER_METHOD_GPS:
548                         LOG_GPS(DBG_LOW, "stop_tracking GPS");
549
550                         gps_set_last_position(&lbs_server->position);
551
552                         g_mutex_lock(&lbs_server->mutex);
553                         lbs_server->gps_client_count--;
554                         g_mutex_unlock(&lbs_server->mutex);
555
556                         if (lbs_server->is_gps_running == FALSE) {
557                                 LOG_GPS(DBG_LOW, "gps- is already stopped");
558                                 return;
559                         }
560
561                         if (lbs_server->gps_client_count <= 0) {
562                                 g_mutex_lock(&lbs_server->mutex);
563                                 lbs_server->gps_client_count = 0;
564
565                                 if (request_stop_session() == TRUE) {
566                                         lbs_server->is_gps_running = FALSE;
567                                         lbs_server->sv_used = FALSE;
568                                         /* remove notify */
569                                         setting_ignore_key_changed(VCONFKEY_LOCATION_ENABLED, __setting_gps_cb);
570                                         g_mutex_unlock(&lbs_server->mutex);
571                                 }
572                         }
573
574                         lbs_server->status = LBS_STATUS_UNAVAILABLE;
575                         lbs_server_emit_status_changed(lbs_server->lbs_dbus_server, LBS_SERVER_METHOD_GPS,
576                                                                                         LBS_STATUS_UNAVAILABLE);
577
578                         break;
579                 case LBS_SERVER_METHOD_NPS:
580                         LOG_NPS(DBG_LOW, "stop_tracking NPS");
581
582                         g_mutex_lock(&lbs_server->mutex);
583                         lbs_server->nps_client_count--;
584                         g_mutex_unlock(&lbs_server->mutex);
585
586                         if (lbs_server->is_nps_running == FALSE) {
587                                 LOG_NPS(DBG_LOW, "nps- is already stopped");
588                                 return;
589                         }
590
591                         if (lbs_server->nps_client_count <= 0) {
592                                 g_mutex_lock(&lbs_server->mutex);
593                                 lbs_server->nps_client_count = 0;
594                                 g_mutex_unlock(&lbs_server->mutex);
595
596                                 LOG_NPS(DBG_LOW, "lbs_server_nps Normal stop");
597                                 nps_stop(lbs_server);
598                         }
599
600                         break;
601                 default:
602                         LOG_GPS(DBG_LOW, "stop_tracking Invalid");
603         }
604 }
605
606 static void update_dynamic_interval_table_foreach_cb(gpointer key, gpointer value, gpointer userdata)
607 {
608         guint *interval_array = (guint *)value;
609         dynamic_interval_updator_user_data *updator_ud = (dynamic_interval_updator_user_data *)userdata;
610         lbs_server_s *lbs_server = updator_ud->lbs_server;
611         int method = updator_ud->method;
612
613         LOG_GPS(DBG_LOW, "method:[%d], key:[%s] interval:[%u], current optimized interval [%u]", method, (char *)key, interval_array[method], lbs_server->optimized_interval_array[method]);
614         if ((lbs_server->temp_minimum_interval > interval_array[method])) {
615                 lbs_server->temp_minimum_interval = interval_array[method];
616         }
617 }
618
619 static gboolean update_pos_tracking_interval(lbs_server_interval_manipulation_type type, const gchar *client, int method, guint interval, gpointer userdata)
620 {
621         LOG_GPS(DBG_LOW, "ENTER >>>");
622         if (userdata == NULL) return FALSE;
623         if (client == NULL) {
624                 LOG_GPS(DBG_ERR, "client is NULL");
625                 return FALSE;
626         }
627
628         if (method < LBS_SERVER_METHOD_GPS || method >= LBS_SERVER_METHOD_SIZE) {
629                 LOG_GPS(DBG_ERR, "unavailable method [%d]", method);
630                 return FALSE;
631         }
632
633         gboolean ret_val = FALSE;
634         lbs_server_s *lbs_server = (lbs_server_s *)userdata;
635
636         /* manipulate logic for dynamic-interval hash table */
637         switch (type) {
638                 case LBS_SERVER_INTERVAL_ADD: {
639                                 LOG_GPS(DBG_LOW, "ADD, client[%s], method[%d], interval[%u]", client, method, interval);
640                                 gchar *client_cpy = NULL;
641                                 client_cpy = g_strdup(client);
642
643                                 guint *interval_array = (guint *) g_hash_table_lookup(lbs_server->dynamic_interval_table, client_cpy);
644                                 if (!interval_array) {
645                                         LOG_GPS(DBG_LOW, "first add key[%s] to interval-table", client);
646                                         interval_array = (guint *)g_malloc0(LBS_SERVER_METHOD_SIZE * sizeof(guint));
647                                         if (!interval_array) {
648                                                 LOG_GPS(DBG_ERR, "interval_array is NULL");
649                                                 g_free(client_cpy);
650                                                 return FALSE;
651                                         }
652                                         g_hash_table_insert(lbs_server->dynamic_interval_table, (gpointer)client_cpy, (gpointer)interval_array);
653                                 }
654                                 interval_array[method] = interval;
655                                 lbs_server->temp_minimum_interval = interval;
656                                 LOG_GPS(DBG_LOW, "ADD done");
657                                 break;
658                         }
659
660                 case LBS_SERVER_INTERVAL_REMOVE: {
661                                 LOG_GPS(DBG_LOW, "REMOVE, client[%s], method[%d]", client, method);
662                                 lbs_server->temp_minimum_interval = 120; /* interval max value */
663                                 guint *interval_array = (guint *) g_hash_table_lookup(lbs_server->dynamic_interval_table, client);
664                                 if (!interval_array) {
665                                         LOG_GPS(DBG_INFO, "Client[%s] Method[%d] is already removed from interval-table", client, method);
666                                         break;
667                                 }
668                                 LOG_GPS(DBG_LOW, "Found interval_array[%d](%p):[%u] from interval-table", method, interval_array, interval_array[method]);
669                                 interval_array[method] = 0;
670
671                                 int i = 0;
672                                 guint interval_each = 0;
673                                 gboolean is_need_remove_client_from_table = TRUE;
674                                 for (i = 0; i < LBS_SERVER_METHOD_SIZE; i++) {
675                                         interval_each = interval_array[i];
676                                         if (interval_each != 0) {
677                                                 LOG_GPS(DBG_LOW, "[%s] method[%d]'s interval is not zero - interval: %d. It will not be removed.", client, i, interval_each);
678                                                 is_need_remove_client_from_table = FALSE;
679                                                 break;
680                                         }
681                                 }
682
683                                 if (is_need_remove_client_from_table) {
684                                         LOG_GPS(DBG_LOW, "is_need_remove_client_from_table is TRUE");
685                                         if (!g_hash_table_remove(lbs_server->dynamic_interval_table, client)) {
686                                                 LOG_GPS(DBG_ERR, "g_hash_table_remove is failed.");
687                                         }
688                                         LOG_GPS(DBG_LOW, "REMOVE done.");
689                                 }
690                                 break;
691                         }
692
693                 case LBS_SERVER_INTERVAL_UPDATE: {
694                                 LOG_GPS(DBG_LOW, "UPDATE client[%s], method[%d], interval[%u]", client, method, interval);
695                                 guint *interval_array = (guint *) g_hash_table_lookup(lbs_server->dynamic_interval_table, client);
696                                 if (!interval_array) {
697                                         LOG_GPS(DBG_LOW, "Client[%s] is not exist in interval-table", client, method);
698                                         break;
699                                 }
700                                 interval_array[method] = interval;
701                                 lbs_server->temp_minimum_interval = interval;
702                                 LOG_GPS(DBG_LOW, "UPDATE done.");
703                                 break;
704                         }
705
706                 default: {
707                                 LOG_GPS(DBG_ERR, "unhandled interval-update type");
708                                 return FALSE;
709                         }
710         }
711
712         /* update logic for optimized-interval value */
713         if (g_hash_table_size(lbs_server->dynamic_interval_table) == 0) {
714                 LOG_GPS(DBG_LOW, "dynamic_interval_table size is zero. It will be updated all value as 0");
715                 int i = 0;
716                 for (i = 0; i < LBS_SERVER_METHOD_SIZE; i++) {
717                         lbs_server->optimized_interval_array[i] = 0;
718                 }
719                 ret_val = FALSE;
720         } else {
721                 LOG_GPS(DBG_LOW, "dynamic_interval_table size is not zero.");
722
723                 dynamic_interval_updator_user_data updator_user_data;
724                 updator_user_data.lbs_server = lbs_server;
725                 updator_user_data.method = method;
726
727                 g_hash_table_foreach(lbs_server->dynamic_interval_table, (GHFunc)update_dynamic_interval_table_foreach_cb, (gpointer)&updator_user_data);
728
729                 if (lbs_server->optimized_interval_array[method] != lbs_server->temp_minimum_interval) {
730                         LOG_GPS(DBG_INFO, "Changing optimized_interval value [%u -> %u] for method [%d]",
731                                         lbs_server->optimized_interval_array[method], lbs_server->temp_minimum_interval, method);
732                         lbs_server->optimized_interval_array[method] = lbs_server->temp_minimum_interval;
733
734                         /* need to send message to provider device */
735                         lbs_server->is_needed_changing_interval = TRUE;
736                 }
737
738                 if (lbs_server->is_needed_changing_interval) {
739                         ret_val = TRUE;
740                 } else {
741                         ret_val = FALSE;
742                 }
743         }
744         LOG_GPS(DBG_LOW, "update_pos_tracking_interval done.");
745         return ret_val;
746 }
747
748 static void request_change_pos_update_interval(int method, gpointer userdata)
749 {
750         LOG_GPS(DBG_LOW, "ENTER >>>");
751         if (!userdata) return;
752
753         lbs_server_s *lbs_server = (lbs_server_s *)userdata;
754         switch (method) {
755                 case LBS_SERVER_METHOD_GPS:
756                         request_change_pos_update_interval_standalone_gps(lbs_server->optimized_interval_array[method]);
757                         break;
758                 default:
759                         break;
760         }
761 }
762
763 static void get_nmea(int *timestamp, gchar **nmea_data, gpointer userdata)
764 {
765         LOG_GPS(DBG_LOW, "ENTER >>>");
766         if (!userdata) return;
767
768         get_nmea_from_server(timestamp, nmea_data);
769
770         LOG_GPS(DBG_LOW, "timestmap: %d, nmea_data: %s", *timestamp, *nmea_data);
771 }
772
773 static void set_options(GVariant *options, const gchar *client, gpointer userdata)
774 {
775         LOG_GPS(DBG_LOW, "ENTER >>>");
776         lbs_server_s *lbs_server = (lbs_server_s *)userdata;
777
778         GVariantIter iter;
779         gchar *key = NULL;
780         GVariant *value = NULL;
781         gboolean ret = FALSE;
782 #ifdef _TIZEN_PUBLIC_
783         char *msg_header = NULL;
784         char *msg_body = NULL;
785         int size = 0;
786 #endif
787         gsize length = 0;
788         char *option = NULL;
789         char *app_id = NULL;
790         guint interval = 0;
791
792         lbs_server_method_e method = 0;
793
794         g_variant_iter_init(&iter, options);
795         ret = g_variant_iter_next(&iter, "{&sv}", &key, &value);
796         if (ret == FALSE) {
797                 LOG_GPS(DBG_ERR, "Invalid GVariant");
798                 return;
799         }
800         if (!g_strcmp0(key, "CMD")) {
801                 LOG_GPS(DBG_LOW, "set_options [%s]", g_variant_get_string(value, &length));
802                 if (!g_strcmp0(g_variant_get_string(value, &length), "START")) {
803
804                         while (g_variant_iter_next(&iter, "{&sv}", &key, &value)) {
805                                 if (!g_strcmp0(key, "METHOD")) {
806                                         method = g_variant_get_int32(value);
807                                         LOG_GPS(DBG_LOW, "METHOD [%d]", method);
808                                 }
809
810                                 if (!g_strcmp0(key, "INTERVAL")) {
811                                         interval = g_variant_get_uint32(value);
812                                         LOG_GPS(DBG_LOW, "INTERVAL [%u]", interval);
813                                 }
814
815                                 if (!g_strcmp0(key, "APP_ID")) {
816                                         app_id = g_variant_dup_string(value, &length);
817                                         LOG_GPS(DBG_LOW, "APP_ID [%s]", app_id);
818                                 }
819                         }
820
821                         if (client) {
822                                 update_pos_tracking_interval(LBS_SERVER_INTERVAL_ADD, client, method, interval, lbs_server);
823                         }
824
825                         if (app_id) {
826                                 if (LBS_SERVER_METHOD_GPS == method) {
827                                         gps_dump_log("START GPS", app_id);
828                                 }
829                                 free(app_id);
830                         }
831
832                         start_tracking(lbs_server, method);
833
834                         if (lbs_server->is_needed_changing_interval) {
835                                 lbs_server->is_needed_changing_interval = FALSE;
836                                 request_change_pos_update_interval(method, (gpointer)lbs_server);
837                         }
838                 } else if (!g_strcmp0(g_variant_get_string(value, &length), "STOP")) {
839
840                         while (g_variant_iter_next(&iter, "{&sv}", &key, &value)) {
841                                 if (!g_strcmp0(key, "METHOD")) {
842                                         method = g_variant_get_int32(value);
843                                         LOG_GPS(DBG_LOW, "METHOD [%d]", method);
844                                 }
845
846                                 if (!g_strcmp0(key, "APP_ID")) {
847                                         app_id = g_variant_dup_string(value, &length);
848                                         LOG_GPS(DBG_LOW, "APP_ID [%s]", app_id);
849                                 }
850                         }
851
852                         if (client) {
853                                 update_pos_tracking_interval(LBS_SERVER_INTERVAL_REMOVE, client, method, interval, lbs_server);
854                         }
855
856                         if (app_id) {
857                                 if (LBS_SERVER_METHOD_GPS == method) {
858                                         gps_dump_log("STOP GPS", app_id);
859                                 }
860                                 free(app_id);
861                         }
862
863                         stop_tracking(lbs_server, method);
864
865                         if (lbs_server->is_needed_changing_interval) {
866                                 lbs_server->is_needed_changing_interval = FALSE;
867                                 request_change_pos_update_interval(method, (gpointer)lbs_server);
868                         }
869                 } else if (!g_strcmp0(g_variant_get_string(value, &length), "START_BATCH")) {
870
871                         int batch_interval = 0;
872                         int batch_period = 0;
873                         while (g_variant_iter_next(&iter, "{&sv}", &key, &value)) {
874
875                                 if (!g_strcmp0(key, "BATCH_INTERVAL")) {
876                                         batch_interval = g_variant_get_int32(value);
877                                         LOG_GPS(DBG_LOW, "BATCH_INTERVAL [%d]", batch_interval);
878                                 } else if (!g_strcmp0(key, "BATCH_PERIOD")) {
879                                         batch_period = g_variant_get_int32(value);
880                                         LOG_GPS(DBG_LOW, "BATCH_PERIOD [%d]", batch_period);
881                                 }
882                         }
883
884                         if (client) {
885                                 update_pos_tracking_interval(LBS_SERVER_INTERVAL_ADD, client, method, batch_interval, lbs_server);
886                         }
887
888                         start_batch_tracking(lbs_server, batch_interval, batch_period);
889
890                         if (lbs_server->is_needed_changing_interval) {
891                                 lbs_server->is_needed_changing_interval = FALSE;
892                                 request_change_pos_update_interval(method, (gpointer)lbs_server);
893                         }
894
895                 } else if (!g_strcmp0(g_variant_get_string(value, &length), "STOP_BATCH")) {
896
897                         if (client) {
898                                 update_pos_tracking_interval(LBS_SERVER_INTERVAL_REMOVE, client, method, interval, lbs_server);
899                         }
900
901                         stop_batch_tracking(lbs_server);
902
903                         if (lbs_server->is_needed_changing_interval) {
904                                 lbs_server->is_needed_changing_interval = FALSE;
905                                 request_change_pos_update_interval(method, (gpointer)lbs_server);
906                         }
907                 }
908 #ifdef _TIZEN_PUBLIC_
909         } else if (!g_strcmp0(g_variant_get_string(value, &length), "SUPLNI")) {
910                 while (g_variant_iter_next(&iter, "{&sv}", &key, &value)) {
911                         if (!g_strcmp0(key, "HEADER")) {
912                                 msg_header = g_variant_dup_string(value, &length);
913                         } else if (!g_strcmp0(key, "BODY")) {
914                                 size = (int) g_variant_get_size(value);
915                                 msg_body = (char *) g_malloc0(sizeof(char) * size);
916                                 memcpy(msg_body, g_variant_get_data(value), size);
917                         } else if (!g_strcmp0(key, "SIZE")) {
918                                 size = (int) g_variant_get_int32(value);
919                         }
920                 }
921                 request_supl_ni_session(msg_header, msg_body, size);
922                 if (msg_header) g_free(msg_header);
923                 if (msg_body) g_free(msg_body);
924         }
925 #endif
926         else if (!g_strcmp0(g_variant_get_string(value, &length), "SET:OPT")) {
927                 LOG_GPS(DBG_LOW, "SET:OPT is called");
928                 gboolean is_update_interval = FALSE, is_update_interval_method = FALSE;
929
930                 while (g_variant_iter_next(&iter, "{&sv}", &key, &value)) {
931
932                         if (!g_strcmp0(key, "OPTION")) {
933                                 option = g_variant_dup_string(value, &length);
934                                 LOG_GPS(DBG_ERR, "option [%s]", option);
935
936                                 if (!g_strcmp0(option, "DELGPS")) {
937                                         if (request_delete_gps_data() != TRUE) {
938                                                 LOG_GPS(DBG_ERR, "Fail to request_delete_gps_data");
939                                         }
940                                 } else if (!g_strcmp0(option, "USE_SV")) {
941                                         g_mutex_lock(&lbs_server->mutex);
942                                         if (lbs_server->sv_used == FALSE)
943                                                 lbs_server->sv_used = TRUE;
944                                         g_mutex_unlock(&lbs_server->mutex);
945                                 }
946                                 g_free(option);
947                         }
948
949                         if (!g_strcmp0(key, "METHOD")) {
950                                 method = g_variant_get_int32(value);
951                                 LOG_GPS(DBG_LOW, "METHOD [%d]", method);
952                                 is_update_interval_method = TRUE;
953                         }
954
955                         if (!g_strcmp0(key, "INTERVAL_UPDATE")) {
956                                 interval = g_variant_get_uint32(value);
957                                 LOG_GPS(DBG_LOW, "INTERVAL_UPDATE [%u] <-- [%u] ", interval, lbs_server->temp_minimum_interval);
958                                 if (interval != lbs_server->temp_minimum_interval)
959                                         is_update_interval = TRUE;
960                         }
961                 }
962
963                 if (is_update_interval && is_update_interval_method && client) {
964                         update_pos_tracking_interval(LBS_SERVER_INTERVAL_UPDATE, client, method, interval, lbs_server);
965                         if (lbs_server->is_needed_changing_interval) {
966                                 lbs_server->is_needed_changing_interval = FALSE;
967                                 request_change_pos_update_interval(method, (gpointer)lbs_server);
968                         }
969                 }
970         }
971 }
972 }
973
974 static gboolean gps_remove_all_clients(lbs_server_s *lbs_server)
975 {
976         LOG_GPS(DBG_LOW, "remove_all_clients GPS");
977         if (lbs_server->gps_client_count <= 0) {
978                 lbs_server->gps_client_count = 0;
979                 return FALSE;
980         }
981
982         lbs_server->gps_client_count = 0;
983         stop_tracking(lbs_server, LBS_SERVER_METHOD_GPS);
984
985         return TRUE;
986 }
987
988 static void shutdown(gpointer userdata, gboolean *shutdown_arr)
989 {
990         LOG_GPS(DBG_LOW, "shutdown callback gps:%d nps:%d", shutdown_arr[LBS_SERVER_METHOD_GPS], shutdown_arr[LBS_SERVER_METHOD_NPS]);
991         lbs_server_s *lbs_server = (lbs_server_s *)userdata;
992
993         if (shutdown_arr[LBS_SERVER_METHOD_GPS]) {
994                 LOG_GPS(DBG_LOW, "-> shutdown GPS");
995                 if (lbs_server->is_gps_running) {
996                         if (gps_remove_all_clients(lbs_server)) {
997                                 LOG_GPS(DBG_ERR, "<<<< Abnormal shutdown >>>>");
998                         }
999                 }
1000         }
1001
1002         if (shutdown_arr[LBS_SERVER_METHOD_NPS]) {
1003                 LOG_NPS(DBG_LOW, "-> shutdown NPS");
1004                 if (lbs_server->is_nps_running) {
1005                         LOG_NPS(DBG_ERR, "lbs_server_nps is running. nps_stop");
1006                         nps_stop(lbs_server);
1007                 }
1008         }
1009
1010         /*
1011         int enabled = 0;
1012         setting_get_int(VCONFKEY_LOCATION_NETWORK_ENABLED, &enabled);
1013         if (enabled == 0) {
1014                 if (lbs_server->loop != NULL) {
1015                         g_main_loop_quit(lbs_server->loop);
1016                 }
1017         } else {
1018                 if (vconf_notify_key_changed(VCONFKEY_LOCATION_NETWORK_ENABLED, _network_enabled_cb, lbs_server)) {
1019                         LOG_NPS(DBG_ERR, "fail to notify VCONFKEY_LOCATION_NETWORK_ENABLED");
1020                 }
1021         }
1022          */
1023 }
1024
1025 static void gps_update_position_cb(pos_data_t *pos, gps_error_t error, void *user_data)
1026 {
1027         LOG_GPS(DBG_LOW, "ENTER >>>");
1028
1029         GVariant *accuracy = NULL;
1030         LbsPositionExtFields fields;
1031
1032         lbs_server_s *lbs_server = (lbs_server_s *)(user_data);
1033
1034         memcpy(&lbs_server->position, pos, sizeof(pos_data_t));
1035
1036         if (lbs_server->status != LBS_STATUS_AVAILABLE) {
1037                 lbs_server_emit_status_changed(lbs_server->lbs_dbus_server, LBS_SERVER_METHOD_GPS, LBS_STATUS_AVAILABLE);
1038                 lbs_server->status = LBS_STATUS_AVAILABLE;
1039         }
1040
1041         fields = (LBS_POSITION_EXT_FIELDS_LATITUDE | LBS_POSITION_EXT_FIELDS_LONGITUDE | LBS_POSITION_EXT_FIELDS_ALTITUDE | LBS_POSITION_EXT_FIELDS_SPEED | LBS_POSITION_EXT_FIELDS_DIRECTION);
1042
1043         accuracy = g_variant_new("(idd)", LBS_ACCURACY_LEVEL_DETAILED, pos->hor_accuracy, pos->ver_accuracy);
1044         if (NULL == accuracy) {
1045                 LOG_GPS(DBG_LOW, "accuracy is NULL");
1046         }
1047
1048         lbs_server_emit_position_changed(lbs_server->lbs_dbus_server, LBS_SERVER_METHOD_GPS,
1049                                                                          fields, pos->timestamp, pos->latitude, pos->longitude, pos->altitude,
1050                                                                          pos->speed, pos->bearing, 0.0, accuracy);
1051 }
1052
1053 static void gps_update_batch_cb(batch_data_t *batch, void *user_data)
1054 {
1055         LOG_GPS(DBG_LOW, "ENTER >>>");
1056         lbs_server_s *lbs_server = (lbs_server_s *)(user_data);
1057         memcpy(&lbs_server->batch, batch, sizeof(batch_data_t));
1058
1059         if (lbs_server->status != LBS_STATUS_AVAILABLE) {
1060                 lbs_server_emit_status_changed(lbs_server->lbs_dbus_server, LBS_SERVER_METHOD_GPS, LBS_STATUS_AVAILABLE);
1061                 lbs_server->status = LBS_STATUS_AVAILABLE;
1062         }
1063
1064         lbs_server_emit_batch_changed(lbs_server->lbs_dbus_server, batch->num_of_location);
1065 }
1066
1067 static void gps_update_satellite_cb(sv_data_t *sv, void *user_data)
1068 {
1069         lbs_server_s *lbs_server = (lbs_server_s *)(user_data);
1070         if (lbs_server->sv_used == FALSE) {
1071                 /*LOG_GPS(DBG_LOW, "sv_used is FALSE"); */
1072                 return;
1073         }
1074
1075         LOG_GPS(DBG_LOW, "ENTER >>>");
1076         int index;
1077         int timestamp = 0;
1078         int satellite_used = 0;
1079         GVariant *used_prn = NULL;
1080         GVariantBuilder *used_prn_builder = NULL;
1081         GVariant *satellite_info = NULL;
1082         GVariantBuilder *satellite_info_builder = NULL;
1083
1084         memcpy(&lbs_server->satellite, sv, sizeof(sv_data_t));
1085         timestamp = sv->timestamp;
1086
1087         used_prn_builder = g_variant_builder_new(G_VARIANT_TYPE("ai"));
1088         for (index = 0; index < sv->num_of_sat; ++index) {
1089                 if (sv->sat[index].used) {
1090                         g_variant_builder_add(used_prn_builder, "i", sv->sat[index].prn);
1091                         ++satellite_used;
1092                 }
1093         }
1094         used_prn = g_variant_builder_end(used_prn_builder);
1095
1096         satellite_info_builder = g_variant_builder_new(G_VARIANT_TYPE("a(iiii)"));
1097         for (index = 0; index < sv->num_of_sat; ++index) {
1098                 g_variant_builder_add(satellite_info_builder, "(iiii)", sv->sat[index].prn,
1099                                                         sv->sat[index].elevation, sv->sat[index].azimuth, sv->sat[index].snr);
1100         }
1101         satellite_info = g_variant_builder_end(satellite_info_builder);
1102
1103         lbs_server_emit_satellite_changed(lbs_server->lbs_dbus_server, timestamp, satellite_used, sv->num_of_sat,
1104                                                                         used_prn, satellite_info);
1105 }
1106
1107 static void gps_update_nmea_cb(nmea_data_t *nmea, void *user_data)
1108 {
1109         lbs_server_s *lbs_server = (lbs_server_s *)(user_data);
1110
1111         if (lbs_server->nmea.data) {
1112                 g_free(lbs_server->nmea.data);
1113                 lbs_server->nmea.len = 0;
1114                 lbs_server->nmea.data = NULL;
1115         }
1116         lbs_server->nmea.timestamp = lbs_server->position.timestamp;
1117         lbs_server->nmea.data = g_malloc(nmea->len + 1);
1118         g_return_if_fail(lbs_server->nmea.data);
1119
1120         g_memmove(lbs_server->nmea.data, nmea->data, nmea->len);
1121         lbs_server->nmea.data[nmea->len] = '\0';
1122         lbs_server->nmea.len = nmea->len;
1123
1124         if (lbs_server->nmea_used == FALSE) {
1125                 /*LOG_GPS(DBG_LOW, "nmea_used is FALSE"); */
1126                 return;
1127         }
1128         LOG_GPS(DBG_LOW, "[%d] %s", lbs_server->nmea.timestamp, lbs_server->nmea.data);
1129         lbs_server_emit_nmea_changed(lbs_server->lbs_dbus_server, lbs_server->nmea.timestamp, lbs_server->nmea.data);
1130 }
1131
1132 int gps_update_geofence_transition(int geofence_id, geofence_zone_state_t transition, double latitude, double longitude, double altitude, double speed, double bearing, double hor_accuracy, void *data)
1133 {
1134         lbs_server_s *lbs_server = (lbs_server_s *)data;
1135         lbs_server_emit_gps_geofence_changed(lbs_server->lbs_dbus_server, geofence_id, transition, latitude, longitude, altitude, speed, bearing, hor_accuracy);
1136         return 0;
1137 }
1138
1139 int gps_update_geofence_service_status(int status, void *data)
1140 {
1141         lbs_server_s *lbs_server = (lbs_server_s *)data;
1142         lbs_server_emit_gps_geofence_status_changed(lbs_server->lbs_dbus_server, status);
1143         return 0;
1144 }
1145
1146 static void add_fence(gint fence_id, gdouble latitude, gdouble longitude, gint radius, gint last_state, gint monitor_states, gint notification_responsiveness, gint unknown_timer, gpointer userdata)
1147 {
1148         request_add_geofence(fence_id, latitude, longitude, radius, last_state, monitor_states, notification_responsiveness, unknown_timer);
1149 }
1150
1151 static void remove_fence(gint fence_id, gpointer userdata)
1152 {
1153         request_delete_geofence(fence_id);
1154 }
1155
1156 static void pause_fence(gint fence_id, gpointer userdata)
1157 {
1158         request_pause_geofence(fence_id);
1159 }
1160
1161 static void resume_fence(gint fence_id, gint monitor_states, gpointer userdata)
1162 {
1163         request_resume_geofence(fence_id, monitor_states);
1164 }
1165
1166 static void nps_init(lbs_server_s *lbs_server_nps);
1167
1168 static void lbs_server_init(lbs_server_s *lbs_server)
1169 {
1170         LOG_GPS(DBG_LOW, "lbs_server_init");
1171
1172         lbs_server->status = LBS_STATUS_UNAVAILABLE;
1173         g_mutex_init(&lbs_server->mutex);
1174
1175         memset(&lbs_server->position, 0x00, sizeof(pos_data_t));
1176         memset(&lbs_server->satellite, 0x00, sizeof(sv_data_t));
1177         memset(&lbs_server->nmea, 0x00, sizeof(nmea_data_t));
1178
1179         lbs_server->is_gps_running = FALSE;
1180         lbs_server->sv_used = FALSE;
1181         lbs_server->nmea_used = FALSE;
1182         lbs_server->gps_client_count = 0;
1183
1184         nps_init(lbs_server);
1185
1186         /* create resource for dynamic-interval */
1187         lbs_server->dynamic_interval_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
1188         lbs_server->optimized_interval_array = (guint *)g_malloc0(LBS_SERVER_METHOD_SIZE * sizeof(guint));
1189         lbs_server->is_needed_changing_interval = FALSE;
1190 }
1191
1192 static void nps_get_last_position(lbs_server_s *lbs_server_nps)
1193 {
1194         int timestamp;
1195         char location[128] = {0,};
1196         char *last_location[MAX_NPS_LOC_ITEM] = {0,};
1197         char *last = NULL;
1198         char *str = NULL;
1199         int index = 0;
1200
1201         setting_get_int(VCONFKEY_LOCATION_NV_LAST_WPS_TIMESTAMP, &timestamp);
1202         str = setting_get_string(VCONFKEY_LOCATION_NV_LAST_WPS_LOCATION);
1203         if (str == NULL) {
1204                 return;
1205         }
1206         snprintf(location, sizeof(location), "%s", str);
1207         free(str);
1208
1209         last_location[index] = (char *)strtok_r(location, ";", &last);
1210         lbs_server_nps->last_pos.timestamp = timestamp;
1211
1212         while (last_location[index] != NULL) {
1213                 switch (index) {
1214                         case 0:
1215                                 lbs_server_nps->last_pos.latitude = strtod(last_location[index], NULL);
1216                                 break;
1217                         case 1:
1218                                 lbs_server_nps->last_pos.longitude = strtod(last_location[index], NULL);
1219                                 break;
1220                         case 2:
1221                                 lbs_server_nps->last_pos.altitude = strtod(last_location[index], NULL);
1222                                 break;
1223                         case 3:
1224                                 lbs_server_nps->last_pos.speed = strtod(last_location[index], NULL);
1225                                 break;
1226                         case 4:
1227                                 lbs_server_nps->last_pos.direction = strtod(last_location[index], NULL);
1228                                 break;
1229                         case 5:
1230                                 lbs_server_nps->last_pos.hor_accuracy = strtod(last_location[index], NULL);
1231                                 break;
1232                         default:
1233                                 break;
1234                 }
1235                 if (++index == MAX_NPS_LOC_ITEM) break;
1236                 last_location[index] = (char *)strtok_r(NULL, ";", &last);
1237         }
1238         LOG_NPS(DBG_LOW, "get nps_last_position timestamp : %d", lbs_server_nps->last_pos.timestamp);
1239 }
1240
1241 static void nps_init(lbs_server_s *lbs_server_nps)
1242 {
1243         LOG_NPS(DBG_LOW, "nps_init");
1244
1245         lbs_server_nps->handle = NULL;
1246         lbs_server_nps->period = 5000;
1247         nps_set_status(lbs_server_nps, LBS_STATUS_UNAVAILABLE);
1248
1249         lbs_server_nps->pos.fields = LBS_POSITION_EXT_FIELDS_NONE;
1250         lbs_server_nps->pos.timestamp = 0;
1251         lbs_server_nps->pos.latitude = 0.0;
1252         lbs_server_nps->pos.longitude = 0.0;
1253         lbs_server_nps->pos.altitude = 0.0;
1254         lbs_server_nps->pos.acc_level = LBS_POSITION_EXT_FIELDS_NONE;
1255         lbs_server_nps->pos.hor_accuracy = -1.0;
1256         lbs_server_nps->pos.ver_accuracy = -1.0;
1257
1258         lbs_server_nps->last_pos.timestamp = 0;
1259         lbs_server_nps->last_pos.latitude = 0.0;
1260         lbs_server_nps->last_pos.longitude = 0.0;
1261         lbs_server_nps->last_pos.altitude = 0.0;
1262         lbs_server_nps->last_pos.hor_accuracy = 0.0;
1263         lbs_server_nps->last_pos.speed = 0.0;
1264         lbs_server_nps->last_pos.direction = 0.0;
1265
1266 #if !GLIB_CHECK_VERSION (2, 31, 0)
1267         GMutex *mutex_temp = g_mutex_new();
1268         lbs_server_nps->mutex = *mutex_temp;
1269         GCond *cond_temp = g_cond_new();
1270         lbs_server_nps->cond = *cond_temp;
1271 #endif
1272
1273         g_mutex_init(&lbs_server_nps->mutex);
1274         g_cond_init(&lbs_server_nps->cond);
1275
1276         lbs_server_nps->is_nps_running = FALSE;
1277         lbs_server_nps->nps_client_count = 0;
1278
1279         if (!get_nps_plugin_module()->load()) {
1280                 LOG_NPS(DBG_ERR, "lbs_server_nps plugin load() failed.");
1281                 return ;
1282         }
1283
1284         nps_get_last_position(lbs_server_nps);
1285 }
1286
1287 static void nps_deinit(lbs_server_s *lbs_server_nps)
1288 {
1289         LOG_NPS(DBG_LOW, "nps_deinit");
1290         if (get_nps_plugin_module()->unload()) {
1291                 if (lbs_server_nps->is_nps_running) {
1292                         g_mutex_lock(&lbs_server_nps->mutex);
1293                         lbs_server_nps->is_nps_running = FALSE;
1294                         g_cond_signal(&lbs_server_nps->cond);
1295                         g_mutex_unlock(&lbs_server_nps->mutex);
1296                 }
1297
1298                 if (lbs_server_nps->token) {
1299                         g_mutex_lock(&lbs_server_nps->mutex);
1300                         g_free(lbs_server_nps->token);
1301                         g_mutex_unlock(&lbs_server_nps->mutex);
1302                 }
1303         } else {
1304                 LOG_NPS(DBG_ERR, "unload() failed.");
1305         }
1306
1307         lbs_server_nps->handle = NULL;
1308         lbs_server_nps->is_nps_running = FALSE;
1309         lbs_server_nps->nps_client_count = 0;
1310
1311 #if !GLIB_CHECK_VERSION (2, 31, 0)
1312         g_cond_free(&lbs_server_nps->cond);
1313         g_mutex_free(&lbs_server_nps->mutex);
1314 #endif
1315
1316         g_cond_clear(&lbs_server_nps->cond);
1317         g_mutex_clear(&lbs_server_nps->mutex);
1318
1319         nps_set_status(lbs_server_nps, LBS_STATUS_UNAVAILABLE);
1320 }
1321
1322 static void _glib_log(const gchar *log_domain, GLogLevelFlags log_level,
1323                                         const gchar *msg, gpointer user_data)
1324 {
1325         LOG_NPS(DBG_ERR, "GLIB[%d] : %s", log_level, msg);
1326 }
1327
1328 int main(int argc, char **argv)
1329 {
1330         lbs_server_s *lbs_server = NULL;
1331         struct gps_callbacks cb;
1332         int ret_code = 0;
1333         cb.pos_cb = gps_update_position_cb;
1334         cb.batch_cb = gps_update_batch_cb;
1335         cb.sv_cb = gps_update_satellite_cb;
1336         cb.nmea_cb = gps_update_nmea_cb;
1337
1338 #if !GLIB_CHECK_VERSION (2, 31, 0)
1339         if (!g_thread_supported()) {
1340                 g_thread_init(NULL);
1341         }
1342 #endif
1343
1344 #if !GLIB_CHECK_VERSION (2, 35, 0)
1345         g_type_init();
1346 #endif
1347
1348         ret_code = initialize_server(argc, argv);
1349         if (ret_code != 0) {
1350                 LOG_GPS(DBG_ERR, "initialize_server failed");
1351                 return 1;
1352         }
1353
1354         lbs_server = g_new0(lbs_server_s, 1);
1355         if (!lbs_server) {
1356                 LOG_GPS(DBG_ERR, "lbs_server_s create fail");
1357                 return 1;
1358         }
1359         lbs_server_init(lbs_server);
1360         gps_init_log();
1361
1362         register_update_callbacks(&cb, lbs_server);
1363
1364         g_log_set_default_handler(_glib_log, lbs_server);
1365
1366         /* create lbs-dbus server */
1367         ret_code = lbs_server_create(SERVICE_NAME, SERVICE_PATH, "lbs-server", "lbs-server",
1368                                                                 &(lbs_server->lbs_dbus_server), set_options, shutdown, update_pos_tracking_interval,
1369                                                                 request_change_pos_update_interval, get_nmea,
1370                                                                 add_fence, remove_fence, pause_fence, resume_fence, (gpointer)lbs_server);
1371         if (ret_code != LBS_SERVER_ERROR_NONE) {
1372                 LOG_GPS(DBG_ERR, "lbs_server_create failed");
1373                 return 1;
1374         }
1375
1376         LOG_GPS(DBG_LOW, "lbs_server_create called");
1377
1378         lbs_server->loop = g_main_loop_new(NULL, TRUE);
1379         g_main_loop_run(lbs_server->loop);
1380
1381         LOG_GPS(DBG_LOW, "lbs_server deamon Stop....");
1382
1383         gps_deinit_log();
1384
1385         /* destroy resource for dynamic-interval */
1386         g_free(lbs_server->optimized_interval_array);
1387         g_hash_table_destroy(lbs_server->dynamic_interval_table);
1388
1389         /* destroy lbs-dbus server */
1390         lbs_server_destroy(lbs_server->lbs_dbus_server);
1391         LOG_GPS(DBG_LOW, "lbs_server_destroy called");
1392
1393         g_main_loop_unref(lbs_server->loop);
1394
1395         nps_deinit(lbs_server);
1396         g_free(lbs_server);
1397
1398         deinitialize_server();
1399
1400         return 0;
1401 }