tizen 2.4 release
[framework/location/libslp-lbs-plugin-replay.git] / gps-plugin / src / gps_plugin_replay.c
1 /*
2  * gps replay plugin
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 <stdlib.h>
24 #include <string.h>
25 #include <glib.h>
26 #include <errno.h>
27 #include <fcntl.h>
28 #include <sys/time.h>
29 #include <sys/stat.h>
30
31 #include <gps_plugin_intf.h>
32 #include <dd-display.h>
33
34 #include "gps_plugin_debug.h"
35 #include "nmea_parser.h"
36 #include "setting.h"
37
38 #define REPLAY_NMEA_SET_SIZE            4096
39 #define REPLAY_NMEA_SENTENCE_SIZE       128
40
41 #define LBS_SERVER_FOLDER       "/opt/usr/media/lbs-server"
42 #define BATCH_LOG                       LBS_SERVER_FOLDER"/location_batch.log"
43
44 gps_event_cb g_gps_event_cb = NULL;
45 void *g_user_data = NULL;
46
47 typedef struct {
48         FILE *fd;
49         FILE *batch_fd;
50         int interval;
51         int replay_mode;
52
53         int batch_mode;
54         int batch_period;
55         int num_of_batch;
56         time_t batch_start_time;
57
58         pos_data_t *pos_data;
59         batch_data_t *batch_data;
60         sv_data_t *sv_data;
61         nmea_data_t *nmea_data;
62
63         GSource *timeout_src;
64         GMainContext *default_context;
65 } replay_timeout;
66
67 replay_timeout *g_replay_timer = NULL;
68
69 int gps_plugin_replay_gps_init(gps_event_cb gps_event_cb, void *user_data);
70 int gps_plugin_replay_gps_deinit(gps_failure_reason_t *reason_code);
71 int gps_plugin_replay_gps_request(gps_action_t gps_action, void *gps_action_data, gps_failure_reason_t *reason_code);
72
73 static const gps_plugin_interface g_gps_plugin_replay_interface = {
74         gps_plugin_replay_gps_init,
75         gps_plugin_replay_gps_deinit,
76         gps_plugin_replay_gps_request
77 };
78
79 void gps_plugin_replay_pos_event(pos_data_t *data)
80 {
81         gps_event_info_t gps_event;
82         time_t timestamp;
83
84         memset(&gps_event, 0, sizeof(gps_event_info_t));
85         time(&timestamp);
86
87         gps_event.event_id = GPS_EVENT_REPORT_POSITION;
88
89         if (data == NULL) {
90                 LOG_PLUGIN(DBG_ERR, "NULL POS data.");
91                 gps_event.event_data.pos_ind.error = GPS_ERR_COMMUNICATION;
92         } else {
93                 gps_event.event_data.pos_ind.error = GPS_ERR_NONE;
94                 gps_event.event_data.pos_ind.pos.timestamp = timestamp;
95                 gps_event.event_data.pos_ind.pos.latitude = data->latitude;
96                 gps_event.event_data.pos_ind.pos.longitude = data->longitude;
97                 gps_event.event_data.pos_ind.pos.altitude = data->altitude;
98                 gps_event.event_data.pos_ind.pos.speed = data->speed;
99                 gps_event.event_data.pos_ind.pos.bearing = data->bearing;
100                 gps_event.event_data.pos_ind.pos.hor_accuracy = data->hor_accuracy;
101                 gps_event.event_data.pos_ind.pos.ver_accuracy = data->ver_accuracy;
102         }
103
104         if (g_gps_event_cb != NULL) {
105                 g_gps_event_cb(&gps_event, g_user_data);
106         }
107 }
108
109 void gps_plugin_replay_batch_event(pos_data_t *data, replay_timeout *timer)
110 {
111         time_t timestamp;
112         time(&timestamp);
113
114         if (timer->batch_fd == NULL) {
115                 if (timer->batch_mode == BATCH_MODE_ON) {
116
117                         struct stat st = {0};
118                         if (stat(LBS_SERVER_FOLDER, &st) == -1) {
119                                 if (mkdir(LBS_SERVER_FOLDER, 0777) == -1) {
120                                         LOG_PLUGIN(DBG_ERR, "Fail to create lbs-server folder");
121                                         return ;
122                                 }
123                         }
124
125                         timer->batch_fd = fopen(BATCH_LOG, "w+");
126                         if (timer->batch_fd == NULL) {
127                                 LOG_PLUGIN(DBG_ERR, "Fail to open file [Not available batch_fd]");
128                                 return ;
129                         }
130                 }
131         }
132
133         if (data != NULL) {
134                 if (timer->batch_mode == BATCH_MODE_ON) {
135                         int ret = -1;
136                         char buf[256] = {0, };
137
138                         g_snprintf(buf, 256, "%ld;%.6lf;%.6lf;%.2lf;%.2lf;%.2lf;%.2lf;%.2lf;\n", timestamp, data->latitude, data->longitude, data->altitude, data->speed, data->bearing, data->hor_accuracy, data->ver_accuracy);
139                         LOG_PLUGIN(DBG_LOW, "Add location info to batch file [%s]", buf);
140
141                         ret = fwrite(buf, 1, strlen(buf), timer->batch_fd);
142                         if (ret != strlen(buf)) {
143                                 LOG_PLUGIN(DBG_ERR, "Fail to write file[%s]", BATCH_LOG);
144                         }
145
146                         (timer->num_of_batch)++ ;
147                 }
148         }
149
150         if ((timestamp - timer->batch_start_time) >= timer->batch_period) {
151                 LOG_PLUGIN(DBG_LOW, "Batch invoked, Batch interval is expired or Batch stopped");
152                 gps_event_info_t gps_event;
153                 memset(&gps_event, 0, sizeof(gps_event_info_t));
154
155                 gps_event.event_id = GPS_EVENT_REPORT_BATCH;
156                 timer->batch_start_time = timestamp;
157
158                 if (timer->num_of_batch < 1) {
159                         LOG_PLUGIN(DBG_ERR, "There is no Batch data");
160                         gps_event.event_data.batch_ind.error = GPS_ERR_COMMUNICATION;
161                 } else {
162                         gps_event.event_data.batch_ind.error = GPS_ERR_NONE;
163                         gps_event.event_data.batch_ind.batch.num_of_location = timer->num_of_batch;
164                 }
165
166                 if (g_gps_event_cb != NULL) {
167                         g_gps_event_cb(&gps_event, g_user_data);
168                         timer->num_of_batch = 0;
169                 }
170
171                 if (timer->batch_fd != NULL) {
172                         fclose(timer->batch_fd);
173                         timer->batch_fd = NULL;
174                 }
175         }
176 }
177
178 void gps_plugin_replay_sv_event(sv_data_t *data)
179 {
180         int i;
181         gps_event_info_t gps_event;
182         time_t timestamp;
183
184         memset(&gps_event, 0, sizeof(gps_event_info_t));
185         time(&timestamp);
186         gps_event.event_id = GPS_EVENT_REPORT_SATELLITE;
187
188         if (data == NULL) {
189                 LOG_PLUGIN(DBG_ERR, "NULL SV data.");
190                 gps_event.event_data.sv_ind.error = GPS_ERR_COMMUNICATION;
191         } else {
192                 gps_event.event_data.sv_ind.error = GPS_ERR_NONE;
193                 gps_event.event_data.sv_ind.sv.timestamp = timestamp;
194                 gps_event.event_data.sv_ind.sv.pos_valid = data->pos_valid;
195                 gps_event.event_data.sv_ind.sv.num_of_sat = data->num_of_sat;
196                 for (i = 0; i < data->num_of_sat; i++) {
197                         gps_event.event_data.sv_ind.sv.sat[i].used = data->sat[i].used;
198                         gps_event.event_data.sv_ind.sv.sat[i].prn = data->sat[i].prn;
199                         gps_event.event_data.sv_ind.sv.sat[i].snr = data->sat[i].snr;
200                         gps_event.event_data.sv_ind.sv.sat[i].elevation = data->sat[i].elevation;
201                         gps_event.event_data.sv_ind.sv.sat[i].azimuth = data->sat[i].azimuth;
202                 }
203         }
204
205         if (g_gps_event_cb != NULL) {
206                 g_gps_event_cb(&gps_event, g_user_data);
207         }
208 }
209
210 void gps_plugin_replay_nmea_event(nmea_data_t *data)
211 {
212         gps_event_info_t gps_event;
213         time_t timestamp;
214
215         memset(&gps_event, 0, sizeof(gps_event_info_t));
216         time(&timestamp);
217
218         gps_event.event_id = GPS_EVENT_REPORT_NMEA;
219
220         if (data == NULL) {
221                 LOG_PLUGIN(DBG_ERR, "NULL NMEA data.");
222                 gps_event.event_data.nmea_ind.error = GPS_ERR_COMMUNICATION;
223         } else {
224                 if (data->len > REPLAY_NMEA_SENTENCE_SIZE) {
225                         LOG_PLUGIN(DBG_WARN, "The Size of NMEA[ %d ] is larger then max ", data->len);
226                         data->len = REPLAY_NMEA_SENTENCE_SIZE;
227                         gps_event.event_data.nmea_ind.error = GPS_ERR_COMMUNICATION;
228                 } else {
229                         gps_event.event_data.nmea_ind.error = GPS_ERR_NONE;
230                 }
231                 gps_event.event_data.nmea_ind.nmea.timestamp = timestamp;
232                 gps_event.event_data.nmea_ind.nmea.len = data->len;
233                 gps_event.event_data.nmea_ind.nmea.data = (char *)malloc(data->len);
234                 g_return_if_fail(gps_event.event_data.nmea_ind.nmea.data);
235
236                 memset(gps_event.event_data.nmea_ind.nmea.data, 0x00, data->len);
237                 memcpy(gps_event.event_data.nmea_ind.nmea.data, data->data, data->len);
238         }
239
240         if (g_gps_event_cb != NULL) {
241                 g_gps_event_cb(&gps_event, g_user_data);
242         }
243
244         if (gps_event.event_data.nmea_ind.nmea.data != NULL) {
245                 free(gps_event.event_data.nmea_ind.nmea.data);
246                 gps_event.event_data.nmea_ind.nmea.data = NULL;
247         }
248 }
249
250 void gps_plugin_respond_start_session(gboolean ret)
251 {
252         gps_event_info_t gps_event;
253         gps_event.event_id = GPS_EVENT_START_SESSION;
254
255         if (ret == TRUE) {
256                 gps_event.event_data.start_session_rsp.error = GPS_ERR_NONE;
257         } else {
258                 gps_event.event_data.start_session_rsp.error = GPS_ERR_COMMUNICATION;
259         }
260
261         if (g_gps_event_cb != NULL) {
262                 g_gps_event_cb(&gps_event, g_user_data);
263         }
264 }
265
266 void gps_plugin_respond_stop_session(void)
267 {
268         gps_event_info_t gps_event;
269
270         gps_event.event_id = GPS_EVENT_STOP_SESSION;
271         gps_event.event_data.stop_session_rsp.error = GPS_ERR_NONE;
272
273         if (g_gps_event_cb != NULL) {
274                 g_gps_event_cb(&gps_event, g_user_data);
275         }
276 }
277
278 gboolean gps_plugin_replay_read_nmea(replay_timeout *timer, char *nmea_data)
279 {
280         gboolean ret = FALSE;
281         int ref = 0;
282         char buf[REPLAY_NMEA_SENTENCE_SIZE] = { 0, };
283
284         if (timer->fd == NULL) {
285                 LOG_PLUGIN(DBG_ERR, "nmea fd is NULL");
286                 return FALSE;
287         }
288
289         if (nmea_data == NULL) {
290                 LOG_PLUGIN(DBG_ERR, "nmea_data is NULL");
291                 fclose(timer->fd);
292                 timer->fd = NULL;
293                 return FALSE;
294         }
295
296         while (fgets(buf, REPLAY_NMEA_SENTENCE_SIZE, timer->fd) != NULL) {
297                 if (strncmp(buf, "$GPGGA", 6) == 0) {
298                         ref++;
299                         if (ref > 1) {
300                                 fseek(timer->fd, -strlen(buf), SEEK_CUR);
301                                 LOG_PLUGIN(DBG_LOW, "2nd GPGGA : stop to read nmea data");
302                                 ret = TRUE;
303                                 break;
304                         } else if (ref == 1) {
305                                 LOG_PLUGIN(DBG_LOW, "1st GPGGA : start to read nmea data");
306                                 strncpy(nmea_data, buf, strlen(buf));
307                         }
308                 } else {
309                         if (strlen(nmea_data) + strlen(buf) > REPLAY_NMEA_SET_SIZE) {
310                                 LOG_PLUGIN(DBG_ERR, "read nmea data size is too long");
311                                 break;
312                         } else {
313                                 strncat(nmea_data, buf, strlen(buf));
314                         }
315                 }
316                 timer->nmea_data->len = strlen(buf);
317                 timer->nmea_data->data = buf;
318                 gps_plugin_replay_nmea_event(timer->nmea_data);
319         }
320
321         if (feof(timer->fd)) {
322                 LOG_PLUGIN(DBG_ERR, "end of file");
323                 rewind(timer->fd);
324                 ret = TRUE;
325         } else {
326                 LOG_PLUGIN(DBG_LOW, "read nmea data [%s]", nmea_data);
327         }
328         return ret;
329 }
330
331 gboolean gps_plugin_replay_read_manual(pos_data_t *pos_data)
332 {
333         gboolean ret = TRUE;
334
335         if (setting_get_double(VCONFKEY_LOCATION_MANUAL_LATITUDE, &pos_data->latitude) == FALSE) {
336                 LOG_PLUGIN(DBG_ERR, "Fail to get latitude");
337                 ret = FALSE;
338         }
339         if (setting_get_double(VCONFKEY_LOCATION_MANUAL_LONGITUDE, &pos_data->longitude) == FALSE) {
340                 LOG_PLUGIN(DBG_ERR, "Fail to get longitude");
341                 ret = FALSE;
342         }
343         if (setting_get_double(VCONFKEY_LOCATION_MANUAL_ALTITUDE, &pos_data->altitude) == FALSE) {
344                 LOG_PLUGIN(DBG_ERR, "Fail to get altitude");
345                 ret = FALSE;
346         }
347
348         return ret;
349 }
350
351 gboolean gps_plugin_replay_timeout_cb(gpointer data)
352 {
353         gboolean ret = FALSE;
354         read_error_t err = READ_SUCCESS;
355         char nmea_data[REPLAY_NMEA_SET_SIZE] = { 0, };
356         replay_timeout *timer = (replay_timeout *) data;
357
358         if (timer == NULL) {
359                 LOG_PLUGIN(DBG_ERR, "replay handel[timer] is NULL");
360                 return FALSE;
361         }
362
363         memset(timer->pos_data, 0, sizeof(pos_data_t));
364         memset(timer->batch_data, 0, sizeof(batch_data_t));
365         memset(timer->sv_data, 0, sizeof(sv_data_t));
366
367         if (timer->replay_mode == REPLAY_NMEA) {
368                 if (gps_plugin_replay_read_nmea(timer, nmea_data) == FALSE) {
369                         LOG_PLUGIN(DBG_ERR, "Fail to read nmea data from file");
370                         return FALSE;
371                 } else {
372                         err = nmea_parser(nmea_data, timer->pos_data, timer->sv_data);
373                         if (err == READ_ERROR) {
374                                 LOG_PLUGIN(DBG_ERR, "Fail to parser nmea data from file");
375                                 /*return FALSE; */
376                         } else if (err == READ_NOT_FIXED) {
377                                 LOG_PLUGIN(DBG_LOW, "GPS position is not fixed");
378                                 timer->sv_data->pos_valid = FALSE;
379                         }
380                 }
381         } else if (timer->replay_mode == REPLAY_MANUAL) {
382                 if (gps_plugin_replay_read_manual(timer->pos_data) == FALSE) {
383                         LOG_PLUGIN(DBG_ERR, "Fail to read manual data");
384                         err = READ_ERROR;
385                         return FALSE;
386                 } else {
387                         timer->sv_data->pos_valid = TRUE;
388                         err = READ_SUCCESS;
389                 }
390         } else if (timer->replay_mode == REPLAY_OFF) {
391                 LOG_PLUGIN(DBG_WARN, "replay_mode is OFF");
392                 err = READ_NOT_FIXED;
393                 timer->sv_data->pos_valid = FALSE;
394         }
395
396         if (g_gps_event_cb != NULL) {
397                 if (err != READ_NOT_FIXED) {
398                         gps_plugin_replay_pos_event(timer->pos_data);
399                 }
400                 gps_plugin_replay_sv_event(timer->sv_data);
401         }
402         ret = TRUE;
403         return ret;
404 }
405
406 gboolean gps_plugin_batch_replay_timeout_cb(gpointer data)
407 {
408         gboolean ret = FALSE;
409         read_error_t err = READ_SUCCESS;
410         char nmea_data[REPLAY_NMEA_SET_SIZE] = { 0, };
411         replay_timeout *timer = (replay_timeout *) data;
412
413         if (timer == NULL) {
414                 LOG_PLUGIN(DBG_ERR, "replay handel[timer] is NULL");
415                 return FALSE;
416         }
417
418         memset(timer->pos_data, 0, sizeof(pos_data_t));
419         memset(timer->batch_data, 0, sizeof(batch_data_t));
420         memset(timer->sv_data, 0, sizeof(sv_data_t));
421
422         if (timer->replay_mode == REPLAY_NMEA) {
423                 if (gps_plugin_replay_read_nmea(timer, nmea_data) == FALSE) {
424                         LOG_PLUGIN(DBG_ERR, "Fail to read nmea data from file");
425                         return FALSE;
426                 } else {
427                         err = nmea_parser(nmea_data, timer->pos_data, timer->sv_data);
428                         if (err == READ_ERROR) {
429                                 LOG_PLUGIN(DBG_ERR, "Fail to parser nmea data from file");
430                         } else if (err == READ_NOT_FIXED) {
431                                 LOG_PLUGIN(DBG_LOW, "GPS position is not fixed");
432                                 timer->sv_data->pos_valid = FALSE;
433                         }
434                 }
435         } else if (timer->replay_mode == REPLAY_MANUAL) {
436                 if (gps_plugin_replay_read_manual(timer->pos_data) == FALSE) {
437                         LOG_PLUGIN(DBG_ERR, "Fail to read manual data");
438                         err = READ_ERROR;
439                         return FALSE;
440                 } else {
441                         timer->sv_data->pos_valid = TRUE;
442                         err = READ_SUCCESS;
443                 }
444         } else if (timer->replay_mode == REPLAY_OFF) {
445                 LOG_PLUGIN(DBG_WARN, "replay_mode is OFF");
446                 err = READ_NOT_FIXED;
447                 timer->sv_data->pos_valid = FALSE;
448         }
449
450         if (g_gps_event_cb != NULL) {
451                 if (timer->batch_mode == BATCH_MODE_ON) {
452                         gps_plugin_replay_batch_event(timer->pos_data, timer);
453                 }
454         }
455         ret = TRUE;
456         return ret;
457 }
458
459 void gps_plugin_stop_replay_mode(replay_timeout *timer)
460 {
461         if (timer->replay_mode == REPLAY_NMEA && fclose(timer->fd) != 0) {
462                 LOG_PLUGIN(DBG_ERR, "fclose failed");
463         }
464         timer->fd = NULL;
465
466         if (timer->timeout_src != NULL && timer->default_context != NULL && !g_source_is_destroyed(timer->timeout_src)) {
467                 if (timer->default_context == g_source_get_context(timer->timeout_src)) {
468                         g_source_destroy(timer->timeout_src);
469                         LOG_PLUGIN(DBG_LOW, "g_source_destroy timeout_src");
470                 } else {
471                         LOG_PLUGIN(DBG_WARN, "timer->timeout_src is attatched to 0x%x (actual 0x%x)",
472                                         g_source_get_context(timer->timeout_src), timer->default_context);
473                 }
474                 timer->timeout_src = NULL;
475                 timer->default_context = NULL;
476         } else {
477                 LOG_PLUGIN(DBG_WARN, "timeout_src or default_context is NULL or timeout_src is already destroyed");
478         }
479         gps_plugin_respond_stop_session();
480
481         display_unlock_state(LCD_OFF, PM_RESET_TIMER);
482         LOG_PLUGIN(DBG_LOW, "display_unlock_state(LCD_OFF, PM_RESET_TIMER);");
483 }
484
485 gboolean gps_plugin_get_nmea_fd(replay_timeout *timer)
486 {
487         char replay_file_path[256];
488         char *str;
489
490         str = setting_get_string(VCONFKEY_LOCATION_NMEA_FILE_NAME);
491         if (str == NULL) {
492                 return FALSE;
493         }
494         snprintf(replay_file_path, sizeof(replay_file_path), NMEA_FILE_PATH"%s", str);
495         SECLOG_PLUGIN(DBG_ERR, "replay file name : %s", replay_file_path);
496         free(str);
497
498         timer->fd = fopen(replay_file_path, "r");
499         if (timer->fd == NULL) {
500                 SECLOG_PLUGIN(DBG_ERR, "fopen(%s) failed", replay_file_path);
501                 timer->fd = fopen(DEFAULT_NMEA_LOG, "r");
502                 if (timer->fd == NULL) {
503                         SECLOG_PLUGIN(DBG_ERR, "fopen(%s) failed", DEFAULT_NMEA_LOG);
504                         return FALSE;
505                 }
506         }
507         return TRUE;
508 }
509
510 gboolean gps_plugin_start_replay_mode(replay_timeout *timer)
511 {
512         gboolean ret = FALSE;
513
514         if (timer->replay_mode == REPLAY_NMEA) {
515                 if (gps_plugin_get_nmea_fd(timer) == FALSE) {
516                         return FALSE;
517                 }
518         }
519
520         if (timer->default_context == NULL) {
521                 timer->default_context = g_main_context_default();
522                 if (timer->default_context == NULL) {
523                         return ret;
524                 }
525         }
526
527         if (timer->timeout_src != NULL) {
528                 LOG_PLUGIN(DBG_ERR, "timeout_src is already existed");
529                 ret = FALSE;
530         } else {
531                 timer->timeout_src = g_timeout_source_new_seconds(timer->interval);
532                 if (timer->timeout_src != NULL) {
533                         g_source_set_callback(timer->timeout_src, &gps_plugin_replay_timeout_cb, timer, NULL);
534                         if (g_source_attach(timer->timeout_src, timer->default_context) > 0) {
535                                 LOG_PLUGIN(DBG_LOW, "timeout_src(0x%x) is created & attatched to 0x%x", timer->timeout_src, timer->default_context);
536                                 ret = TRUE;
537                         } else {
538                                 gps_plugin_stop_replay_mode(timer);
539                                 ret = FALSE;
540                         }
541                 }
542         }
543
544         display_lock_state(LCD_OFF, STAY_CUR_STATE, 0);
545         LOG_PLUGIN(DBG_LOW, "display_lock_state(LCD_OFF, STAY_CUR_STATE, 0);");
546
547         gps_plugin_respond_start_session(ret);
548
549         return ret;
550 }
551
552 gboolean gps_plugin_start_batch_mode(replay_timeout *timer, int batch_interval, int batch_period)
553 {
554         gboolean ret = FALSE;
555         time_t timestamp;
556         time(&timestamp);
557
558         if (timer->replay_mode == REPLAY_NMEA) {
559                 if (gps_plugin_get_nmea_fd(timer) == FALSE) {
560                         return FALSE;
561                 }
562         }
563
564         if (timer->default_context == NULL) {
565                 timer->default_context = g_main_context_default();
566                 if (timer->default_context == NULL) {
567                         return ret;
568                 }
569         }
570
571         if (timer->timeout_src != NULL) {
572                 LOG_PLUGIN(DBG_ERR, "timeout_src is already existed");
573                 ret = FALSE;
574         } else {
575                 timer->timeout_src = g_timeout_source_new_seconds(batch_interval);
576                 if (timer->timeout_src != NULL) {
577                         g_source_set_callback(timer->timeout_src, &gps_plugin_batch_replay_timeout_cb, timer, NULL);
578                         if (g_source_attach(timer->timeout_src, timer->default_context) > 0) {
579                                 LOG_PLUGIN(DBG_LOW, "timeout_src(0x%x) is created & attatched to 0x%x", timer->timeout_src, timer->default_context);
580                                 ret = TRUE;
581                         } else {
582                                 gps_plugin_stop_replay_mode(timer);
583                                 ret = FALSE;
584                         }
585                 }
586         }
587
588         gps_plugin_respond_start_session(ret);
589
590         timer->batch_mode = BATCH_MODE_ON;
591         timer->batch_period = batch_period;
592         timer->batch_start_time = timestamp;
593
594         return ret;
595 }
596
597 void gps_plugin_stop_batch_mode(replay_timeout *timer)
598 {
599         if (timer->batch_mode == BATCH_MODE_ON) {
600                 timer->batch_mode = BATCH_MODE_OFF;
601         }
602
603         if (timer->batch_fd != NULL) {
604                 fclose(timer->batch_fd);
605                 timer->batch_fd = NULL;
606                 timer->num_of_batch = 0;
607         }
608 }
609
610 static void replay_mode_changed_cb(keynode_t *key, void *data)
611 {
612         if (setting_get_int(VCONFKEY_LOCATION_REPLAY_MODE, &g_replay_timer->replay_mode) == FALSE) {
613                 g_replay_timer->replay_mode = REPLAY_OFF;
614         }
615
616         if (g_replay_timer->replay_mode == REPLAY_NMEA) {
617                 if (gps_plugin_get_nmea_fd(g_replay_timer) == FALSE) {
618                         LOG_PLUGIN(DBG_ERR, "Fail to get nmea fd.");
619                 }
620         } else {
621                 if (g_replay_timer->fd != NULL) {
622                         fclose(g_replay_timer->fd);
623                         g_replay_timer->fd = NULL;
624                 }
625         }
626         return;
627 }
628
629 replay_timeout *gps_plugin_replay_timer_init()
630 {
631         replay_timeout *timer = NULL;
632
633         timer = (replay_timeout *) malloc(sizeof(replay_timeout));
634         if (timer == NULL) {
635                 LOG_PLUGIN(DBG_ERR, "replay_timeout allocation is failed.");
636                 return NULL;
637         }
638
639         timer->fd = NULL;
640         timer->interval = 1;
641
642         timer->batch_fd = NULL;
643         timer->num_of_batch = 0;
644         timer->batch_mode = BATCH_MODE_OFF;
645
646         if (setting_get_int(VCONFKEY_LOCATION_REPLAY_MODE, &timer->replay_mode) == FALSE) {
647                 timer->replay_mode = REPLAY_OFF;
648         }
649         setting_notify_key_changed(VCONFKEY_LOCATION_REPLAY_MODE, replay_mode_changed_cb);
650
651         timer->pos_data = (pos_data_t *) malloc(sizeof(pos_data_t));
652         if (timer->pos_data == NULL) {
653                 LOG_PLUGIN(DBG_ERR, "pos_data allocation is failed.");
654                 free(timer);
655                 return NULL;
656         }
657
658         timer->batch_data = (batch_data_t *) malloc(sizeof(batch_data_t));
659         if (timer->batch_data == NULL) {
660                 LOG_PLUGIN(DBG_ERR, "batch_data allocation is failed.");
661                 free(timer->pos_data);
662                 free(timer);
663                 return NULL;
664         }
665
666         timer->sv_data = (sv_data_t *) malloc(sizeof(sv_data_t));
667         if (timer->sv_data == NULL) {
668                 LOG_PLUGIN(DBG_ERR, "sv_data allocation is failed.");
669                 free(timer->pos_data);
670                 free(timer->batch_data);
671                 free(timer);
672                 return NULL;
673         }
674
675         timer->nmea_data = (nmea_data_t *) malloc(sizeof(nmea_data_t));
676         if (timer->nmea_data == NULL) {
677                 LOG_PLUGIN(DBG_ERR, "nmea_data allocation is failed.");
678                 free(timer->pos_data);
679                 free(timer->batch_data);
680                 free(timer->sv_data);
681                 free(timer);
682                 return NULL;
683         }
684
685         timer->timeout_src = NULL;
686         timer->default_context = NULL;
687
688         return timer;
689 }
690
691 void gps_plugin_replay_timer_deinit(replay_timeout *timer)
692 {
693         if (timer == NULL) {
694                 return;
695         }
696
697         if (timer->pos_data != NULL) {
698                 free(timer->pos_data);
699                 timer->pos_data = NULL;
700         }
701         if (timer->sv_data != NULL) {
702                 free(timer->sv_data);
703                 timer->sv_data = NULL;
704         }
705         if (timer->nmea_data != NULL) {
706                 free(timer->nmea_data);
707                 timer->nmea_data = NULL;
708         }
709
710         setting_ignore_key_changed(VCONFKEY_LOCATION_REPLAY_MODE, replay_mode_changed_cb);
711
712         free(timer);
713         timer = NULL;
714 }
715
716 int gps_plugin_replay_gps_init(gps_event_cb gps_event_cb, void *user_data)
717 {
718         g_gps_event_cb = gps_event_cb;
719         g_replay_timer = gps_plugin_replay_timer_init();
720         g_user_data = user_data;
721
722         return TRUE;
723 }
724
725 int gps_plugin_replay_gps_deinit(gps_failure_reason_t *reason_code)
726 {
727         gps_plugin_replay_timer_deinit(g_replay_timer);
728         g_gps_event_cb = NULL;
729         g_user_data = NULL;
730
731         return TRUE;
732 }
733
734 int gps_plugin_replay_gps_request(gps_action_t gps_action, void *gps_action_data, gps_failure_reason_t *reason_code)
735 {
736         gps_action_start_data_t *gps_start_data = gps_action_data;
737
738         switch (gps_action) {
739                 case GPS_ACTION_SEND_PARAMS:
740                         break;
741                 case GPS_ACTION_START_SESSION:
742                         gps_plugin_start_replay_mode(g_replay_timer);
743                         break;
744                 case GPS_ACTION_STOP_SESSION:
745                         gps_plugin_stop_replay_mode(g_replay_timer);
746                         break;
747                 case GPS_ACTION_START_BATCH:
748                         gps_plugin_start_batch_mode(g_replay_timer, gps_start_data->interval, gps_start_data->period);
749                         break;
750                 case GPS_ACTION_STOP_BATCH:
751                         gps_plugin_stop_batch_mode(g_replay_timer);
752                         gps_plugin_stop_replay_mode(g_replay_timer);
753                         break;
754                 case GPS_INDI_SUPL_VERIFICATION:
755                 case GPS_INDI_SUPL_DNSQUERY:
756                 case GPS_ACTION_START_FACTTEST:
757                 case GPS_ACTION_STOP_FACTTEST:
758                 case GPS_ACTION_REQUEST_SUPL_NI:
759                         LOG_PLUGIN(DBG_LOW, "Don't use action type : [ %d ]", gps_action);
760                         break;
761                 default:
762                         break;
763         }
764
765         return TRUE;
766 }
767
768 EXPORT_API const gps_plugin_interface *get_gps_plugin_interface()
769 {
770         return &g_gps_plugin_replay_interface;
771 }