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