loc_eng.cpp revision ae1989429bcdce118229b4b728daaed99b039e8f
1/******************************************************************************
2  @file:  loc_eng.cpp
3  @brief:
4
5  DESCRIPTION
6    This file defines the implemenation for GPS hardware abstraction layer.
7
8  INITIALIZATION AND SEQUENCING REQUIREMENTS
9
10  -----------------------------------------------------------------------------
11Copyright (c) 2009, QUALCOMM USA, INC.
12
13All rights reserved.
14
15Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
16
17�         Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
18
19�         Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
20
21�         Neither the name of the QUALCOMM USA, INC.  nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
22
23THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  -----------------------------------------------------------------------------
25
26******************************************************************************/
27
28/*=====================================================================
29$Header: $
30$DateTime: $
31$Author: $
32======================================================================*/
33
34#define LOG_NDDEBUG 0
35
36#include <stdio.h>
37#include <stdlib.h>
38#include <unistd.h>
39#include <ctype.h>
40#include <math.h>
41#include <pthread.h>
42#include <arpa/inet.h>
43#include <netdb.h>
44
45#include <rpc/rpc.h>
46#include "loc_api_rpc_glue.h"
47#include "loc_apicb_appinit.h"
48
49#include <cutils/properties.h>
50#include <cutils/sched_policy.h>
51#include <utils/SystemClock.h>
52
53#include <loc_eng.h>
54#include <loc_eng_ni.h>
55
56#define LOG_TAG "lib_locapi"
57#include <utils/Log.h>
58
59// comment this out to enable logging
60// #undef LOGD
61// #define LOGD(...) {}
62
63#define DEBUG_MOCK_NI 0
64
65// Function declarations for sLocEngInterface
66static int  loc_eng_init(GpsCallbacks* callbacks);
67static int  loc_eng_start();
68static int  loc_eng_stop();
69static int  loc_eng_set_position_mode(GpsPositionMode mode, int fix_frequency);
70static void loc_eng_cleanup();
71static int  loc_eng_inject_time(GpsUtcTime time, int64_t timeReference, int uncertainty);
72static int  loc_eng_inject_location(double latitude, double longitude, float accuracy);
73static void loc_eng_delete_aiding_data (GpsAidingData f);
74static const void* loc_eng_get_extension(const char* name);
75
76// Function declarations for sLocEngAGpsInterface
77static void loc_eng_agps_init(AGpsCallbacks* callbacks);
78static int loc_eng_agps_data_conn_open(const char* apn);
79static int loc_eng_agps_data_conn_closed();
80static int loc_eng_agps_data_conn_failed();
81static int loc_eng_agps_set_server(AGpsType type, const char* hostname, int port);
82
83
84static int32 loc_event_cb (rpc_loc_client_handle_type client_handle,
85                           rpc_loc_event_mask_type loc_event,
86                           const rpc_loc_event_payload_u_type* loc_event_payload);
87static void loc_eng_report_position (const rpc_loc_parsed_position_s_type *location_report_ptr);
88static void loc_eng_report_sv (const rpc_loc_gnss_info_s_type *gnss_report_ptr);
89static void loc_eng_report_status (const rpc_loc_status_event_s_type *status_report_ptr);
90static void loc_eng_report_nmea (const rpc_loc_nmea_report_s_type *nmea_report_ptr);
91static void loc_eng_process_conn_request (const rpc_loc_server_request_s_type *server_request_ptr);
92
93static void* loc_eng_process_deferred_action (void* arg);
94static void loc_eng_process_atl_deferred_action (boolean data_connection_succeeded,
95        boolean data_connection_closed);
96static void loc_eng_delete_aiding_data_deferred_action (void);
97
98static int set_agps_server();
99
100// Defines the GpsInterface in gps.h
101static const GpsInterface sLocEngInterface =
102{
103    sizeof(GpsInterface),
104    loc_eng_init,
105    loc_eng_start,
106    loc_eng_stop,
107    loc_eng_cleanup,
108    loc_eng_inject_time,
109    loc_eng_inject_location,
110    loc_eng_delete_aiding_data,
111    loc_eng_set_position_mode,
112    loc_eng_get_extension,
113};
114
115static const AGpsInterface sLocEngAGpsInterface =
116{
117    sizeof(AGpsInterface),
118    loc_eng_agps_init,
119    loc_eng_agps_data_conn_open,
120    loc_eng_agps_data_conn_closed,
121    loc_eng_agps_data_conn_failed,
122    loc_eng_agps_set_server,
123};
124
125// Global data structure for location engine
126loc_eng_data_s_type loc_eng_data;
127
128/*===========================================================================
129FUNCTION    gps_get_hardware_interface
130
131DESCRIPTION
132   Returns the GPS hardware interaface based on LOC API
133   if GPS is enabled.
134
135DEPENDENCIES
136   None
137
138RETURN VALUE
139   0: success
140
141SIDE EFFECTS
142   N/A
143
144===========================================================================*/
145const GpsInterface* gps_get_hardware_interface ()
146{
147    char propBuf[PROPERTY_VALUE_MAX];
148
149    // check to see if GPS should be disabled
150    property_get("gps.disable", propBuf, "");
151    if (propBuf[0] == '1')
152    {
153        LOGD("gps_get_interface returning NULL because gps.disable=1\n");
154        return NULL;
155    }
156
157    return &sLocEngInterface;
158}
159
160/*===========================================================================
161FUNCTION    loc_eng_init
162
163DESCRIPTION
164   Initialize the location engine, this include setting up global datas
165   and registers location engien with loc api service.
166
167DEPENDENCIES
168   None
169
170RETURN VALUE
171   0: success
172
173SIDE EFFECTS
174   N/A
175
176===========================================================================*/
177static int loc_eng_init(GpsCallbacks* callbacks)
178{
179    // Start the LOC api RPC service
180    loc_api_glue_init ();
181
182    memset (&loc_eng_data, 0, sizeof (loc_eng_data_s_type));
183
184    // LOC ENG module data initialization
185    loc_eng_data.location_cb  = callbacks->location_cb;
186    loc_eng_data.sv_status_cb = callbacks->sv_status_cb;
187    loc_eng_data.status_cb    = callbacks->status_cb;
188    loc_eng_data.nmea_cb    = callbacks->nmea_cb;
189
190    rpc_loc_event_mask_type event = RPC_LOC_EVENT_PARSED_POSITION_REPORT |
191                                    RPC_LOC_EVENT_SATELLITE_REPORT |
192                                    RPC_LOC_EVENT_LOCATION_SERVER_REQUEST |
193                                    RPC_LOC_EVENT_ASSISTANCE_DATA_REQUEST |
194                                    RPC_LOC_EVENT_IOCTL_REPORT |
195                                    RPC_LOC_EVENT_STATUS_REPORT |
196                                    RPC_LOC_EVENT_NMEA_POSITION_REPORT |
197                                    RPC_LOC_EVENT_NI_NOTIFY_VERIFY_REQUEST;
198
199    loc_eng_data.client_handle = loc_open (event, loc_event_cb);
200
201    pthread_mutex_init (&(loc_eng_data.deferred_action_mutex), NULL);
202    pthread_cond_init  (&(loc_eng_data.deferred_action_cond) , NULL);
203    loc_eng_data.deferred_action_thread_need_exit = FALSE;
204
205    loc_eng_data.loc_event = 0;
206    loc_eng_data.data_connection_succeeded = FALSE;
207    loc_eng_data.data_connection_closed = FALSE;
208    loc_eng_data.data_connection_failed = FALSE;
209    memset (loc_eng_data.apn_name, 0, sizeof (loc_eng_data.apn_name));
210
211    loc_eng_data.aiding_data_for_deletion = 0;
212    loc_eng_data.engine_status = GPS_STATUS_NONE;
213
214    // XTRA module data initialization
215    loc_eng_data.xtra_module_data.download_request_cb = NULL;
216
217    // IOCTL module data initialization
218    loc_eng_data.ioctl_data.cb_is_selected  = FALSE;
219    loc_eng_data.ioctl_data.cb_is_waiting   = FALSE;
220    loc_eng_data.ioctl_data.client_handle   = RPC_LOC_CLIENT_HANDLE_INVALID;
221    memset (&(loc_eng_data.ioctl_data.cb_payload),
222            0,
223            sizeof (rpc_loc_ioctl_callback_s_type));
224
225    pthread_mutex_init (&(loc_eng_data.ioctl_data.cb_data_mutex), NULL);
226    pthread_cond_init(&loc_eng_data.ioctl_data.cb_arrived_cond, NULL);
227
228    loc_eng_data.deferred_action_thread = NULL;
229    pthread_create (&(loc_eng_data.deferred_action_thread),
230                    NULL,
231                    loc_eng_process_deferred_action,
232                    NULL);
233
234    LOGD ("loc_eng_init called, client id = %d\n", (int32) loc_eng_data.client_handle);
235    return 0;
236}
237
238/*===========================================================================
239FUNCTION    loc_eng_cleanup
240
241DESCRIPTION
242   Cleans location engine. The location client handle will be released.
243
244DEPENDENCIES
245   None
246
247RETURN VALUE
248   None
249
250SIDE EFFECTS
251   N/A
252
253===========================================================================*/
254static void loc_eng_cleanup()
255{
256    if (loc_eng_data.deferred_action_thread)
257    {
258        /* Terminate deferred action working thread */
259        pthread_mutex_lock (&loc_eng_data.deferred_action_mutex);
260        loc_eng_data.deferred_action_thread_need_exit = TRUE;
261        pthread_cond_signal  (&loc_eng_data.deferred_action_cond);
262        pthread_mutex_unlock (&loc_eng_data.deferred_action_mutex);
263
264        void* ignoredValue;
265        pthread_join(loc_eng_data.deferred_action_thread, &ignoredValue);
266        loc_eng_data.deferred_action_thread = NULL;
267    }
268
269    // clean up
270    (void) loc_close (loc_eng_data.client_handle);
271
272    pthread_mutex_destroy (&loc_eng_data.deferred_action_mutex);
273    pthread_cond_destroy  (&loc_eng_data.deferred_action_cond);
274
275    pthread_mutex_destroy (&loc_eng_data.ioctl_data.cb_data_mutex);
276    pthread_cond_destroy  (&loc_eng_data.ioctl_data.cb_arrived_cond);
277
278// Do not call this as it can result in the ARM9 crashing if it sends events while we are disabled
279//    loc_apicb_app_deinit();
280}
281
282
283/*===========================================================================
284FUNCTION    loc_eng_start
285
286DESCRIPTION
287   Starts the tracking session
288
289DEPENDENCIES
290   None
291
292RETURN VALUE
293   0: success
294
295SIDE EFFECTS
296   N/A
297
298===========================================================================*/
299static int loc_eng_start()
300{
301    int ret_val;
302    LOGD ("loc_eng_start\n");
303
304    if (loc_eng_data.position_mode != GPS_POSITION_MODE_STANDALONE &&
305            loc_eng_data.agps_server_host[0] != 0 &&
306            loc_eng_data.agps_server_port != 0) {
307        int result = set_agps_server();
308        LOGD ("set_agps_server returned = %d\n", result);
309    }
310
311    ret_val = loc_start_fix (loc_eng_data.client_handle);
312
313    if (ret_val != RPC_LOC_API_SUCCESS)
314    {
315        LOGD ("loc_eng_start returned error = %d\n", ret_val);
316    }
317
318    return 0;
319}
320
321
322/*===========================================================================
323FUNCTION    loc_eng_stop
324
325DESCRIPTION
326   Stops the tracking session
327
328DEPENDENCIES
329   None
330
331RETURN VALUE
332   0: success
333
334SIDE EFFECTS
335   N/A
336
337===========================================================================*/
338static int loc_eng_stop()
339{
340    int ret_val;
341
342    LOGD ("loc_eng_stop\n");
343
344    ret_val = loc_stop_fix (loc_eng_data.client_handle);
345    if (ret_val != RPC_LOC_API_SUCCESS)
346    {
347        LOGD ("loc_eng_stop returned error = %d\n", ret_val);
348    }
349
350    return 0;
351}
352
353static int loc_eng_set_gps_lock(rpc_loc_lock_e_type lock_type)
354{
355    rpc_loc_ioctl_data_u_type    ioctl_data;
356    boolean                      ret_val;
357
358    LOGD ("loc_eng_set_gps_lock mode, client = %d, lock_type = %d\n",
359            (int32) loc_eng_data.client_handle, lock_type);
360
361    ioctl_data.rpc_loc_ioctl_data_u_type_u.engine_lock = lock_type;
362    ioctl_data.disc = RPC_LOC_IOCTL_SET_ENGINE_LOCK;
363
364    ret_val = loc_eng_ioctl (loc_eng_data.client_handle,
365                            RPC_LOC_IOCTL_SET_ENGINE_LOCK,
366                            &ioctl_data,
367                            LOC_IOCTL_DEFAULT_TIMEOUT,
368                            NULL /* No output information is expected*/);
369
370    if (ret_val != TRUE)
371    {
372        LOGD ("loc_eng_set_gps_lock mode failed\n");
373    }
374
375    return 0;
376}
377
378/*===========================================================================
379FUNCTION    loc_eng_set_position_mode
380
381DESCRIPTION
382   Sets the mode and fix frequnecy (in seconds) for the tracking session.
383
384DEPENDENCIES
385   None
386
387RETURN VALUE
388   0: success
389
390SIDE EFFECTS
391   N/A
392
393===========================================================================*/
394static int loc_eng_set_position_mode(GpsPositionMode mode, int fix_frequency)
395{
396    rpc_loc_ioctl_data_u_type    ioctl_data;
397    rpc_loc_fix_criteria_s_type *fix_criteria_ptr;
398    boolean                      ret_val;
399
400    LOGD ("loc_eng_set_position mode, client = %d, interval = %d, mode = %d\n",
401            (int32) loc_eng_data.client_handle, fix_frequency, mode);
402
403    loc_eng_data.position_mode = mode;
404    ioctl_data.disc = RPC_LOC_IOCTL_SET_FIX_CRITERIA;
405
406    fix_criteria_ptr = &(ioctl_data.rpc_loc_ioctl_data_u_type_u.fix_criteria);
407    fix_criteria_ptr->valid_mask = RPC_LOC_FIX_CRIT_VALID_MIN_INTERVAL |
408                                   RPC_LOC_FIX_CRIT_VALID_PREFERRED_OPERATION_MODE |
409                                   RPC_LOC_FIX_CRIT_VALID_RECURRENCE_TYPE;
410    fix_criteria_ptr->min_interval = fix_frequency * 1000; // Translate to ms
411    fix_criteria_ptr->recurrence_type = RPC_LOC_PERIODIC_FIX;
412
413    if (mode == GPS_POSITION_MODE_MS_BASED)
414    {
415        fix_criteria_ptr->preferred_operation_mode = RPC_LOC_OPER_MODE_MSB;
416    }
417    else if (mode == GPS_POSITION_MODE_MS_ASSISTED)
418    {
419        fix_criteria_ptr->preferred_operation_mode = RPC_LOC_OPER_MODE_MSA;
420    }
421    // Default: standalone
422    else
423    {
424        fix_criteria_ptr->preferred_operation_mode = RPC_LOC_OPER_MODE_STANDALONE;
425    }
426
427    ret_val = loc_eng_ioctl(loc_eng_data.client_handle,
428                            RPC_LOC_IOCTL_SET_FIX_CRITERIA,
429                            &ioctl_data,
430                            LOC_IOCTL_DEFAULT_TIMEOUT,
431                            NULL /* No output information is expected*/);
432
433    if (ret_val != TRUE)
434    {
435        LOGD ("loc_eng_set_position mode failed\n");
436    }
437
438    return 0;
439}
440
441/*===========================================================================
442FUNCTION    loc_eng_inject_time
443
444DESCRIPTION
445   This is used by Java native function to do time injection.
446
447DEPENDENCIES
448   None
449
450RETURN VALUE
451   RPC_LOC_API_SUCCESS
452
453SIDE EFFECTS
454   N/A
455
456===========================================================================*/
457static int loc_eng_inject_time (GpsUtcTime time, int64_t timeReference, int uncertainty)
458{
459    rpc_loc_ioctl_data_u_type       ioctl_data;
460    rpc_loc_assist_data_time_s_type *time_info_ptr;
461    boolean                          ret_val;
462
463    LOGD ("loc_eng_inject_time, uncertainty = %d\n", uncertainty);
464
465    ioctl_data.disc = RPC_LOC_IOCTL_INJECT_UTC_TIME;
466
467    time_info_ptr = &(ioctl_data.rpc_loc_ioctl_data_u_type_u.assistance_data_time);
468    time_info_ptr->time_utc = time;
469    time_info_ptr->time_utc += (int64_t)(android::elapsedRealtime() - timeReference);
470    time_info_ptr->uncertainty = uncertainty; // Uncertainty in ms
471
472    ret_val = loc_eng_ioctl (loc_eng_data.client_handle,
473                             RPC_LOC_IOCTL_INJECT_UTC_TIME,
474                             &ioctl_data,
475                             LOC_IOCTL_DEFAULT_TIMEOUT,
476                             NULL /* No output information is expected*/);
477
478    if (ret_val != TRUE)
479    {
480        LOGD ("loc_eng_inject_time failed\n");
481    }
482
483    return 0;
484}
485
486static int loc_eng_inject_location (double latitude, double longitude, float accuracy)
487{
488    /* not yet implemented */
489    return 0;
490}
491
492/*===========================================================================
493FUNCTION    loc_eng_delete_aiding_data
494
495DESCRIPTION
496   This is used by Java native function to delete the aiding data. The function
497   updates the global variable for the aiding data to be deleted. If the GPS
498   engine is off, the aiding data will be deleted. Otherwise, the actual action
499   will happen when gps engine is turned off.
500
501DEPENDENCIES
502   Assumes the aiding data type specified in GpsAidingData matches with
503   LOC API specification.
504
505RETURN VALUE
506   RPC_LOC_API_SUCCESS
507
508SIDE EFFECTS
509   N/A
510
511===========================================================================*/
512static void loc_eng_delete_aiding_data (GpsAidingData f)
513{
514    pthread_mutex_lock(&(loc_eng_data.deferred_action_mutex));
515
516    // If this is DELETE ALL
517    if (f == GPS_DELETE_ALL)
518    {
519        loc_eng_data.aiding_data_for_deletion = GPS_DELETE_ALL;
520    }
521    else
522    {
523        // Currently, LOC API only support deletion of all aiding data,
524        // since the Android defined aiding data mask matches with modem,
525        // so just pass them down without any translation
526        loc_eng_data.aiding_data_for_deletion |= f;
527    }
528
529    if ((loc_eng_data.engine_status != GPS_STATUS_SESSION_BEGIN) &&
530        (loc_eng_data.aiding_data_for_deletion != 0))
531    {
532        pthread_cond_signal(&(loc_eng_data.deferred_action_cond));
533
534        // In case gps engine is ON, the assistance data will be deleted when the engine is OFF
535    }
536
537    pthread_mutex_unlock(&(loc_eng_data.deferred_action_mutex));
538}
539
540/*===========================================================================
541FUNCTION    loc_eng_get_extension
542
543DESCRIPTION
544   Get the gps extension to support XTRA.
545
546DEPENDENCIES
547   N/A
548
549RETURN VALUE
550   The GPS extension interface.
551
552SIDE EFFECTS
553   N/A
554
555===========================================================================*/
556static const void* loc_eng_get_extension(const char* name)
557{
558    if (strcmp(name, GPS_XTRA_INTERFACE) == 0)
559    {
560        return &sLocEngXTRAInterface;
561    }
562    else if (strcmp(name, AGPS_INTERFACE) == 0)
563    {
564        return &sLocEngAGpsInterface;
565    }
566    else if (strcmp(name, GPS_NI_INTERFACE) == 0)
567    {
568        return &sLocEngNiInterface;
569    }
570
571    return NULL;
572}
573
574#if DEBUG_MOCK_NI == 1
575/*===========================================================================
576FUNCTION    mock_ni
577
578DESCRIPTION
579   DEBUG tool: simulate an NI request
580
581DEPENDENCIES
582   N/A
583
584RETURN VALUE
585   None
586
587SIDE EFFECTS
588   N/A
589
590===========================================================================*/
591static void* mock_ni(void* arg)
592{
593    static int busy = 0;
594
595    if (busy) return NULL;
596
597    busy = 1;
598
599    sleep(5);
600
601    rpc_loc_client_handle_type           client_handle;
602    rpc_loc_event_mask_type              loc_event;
603    rpc_loc_event_payload_u_type         payload;
604    rpc_loc_ni_event_s_type             *ni_req;
605    rpc_loc_ni_supl_notify_verify_req_s_type *supl_req;
606
607    client_handle = (rpc_loc_client_handle_type) arg;
608
609    loc_event = RPC_LOC_EVENT_NI_NOTIFY_VERIFY_REQUEST;
610    payload.disc = loc_event;
611
612    ni_req = &payload.rpc_loc_event_payload_u_type_u.ni_request;
613    ni_req->event = RPC_LOC_NI_EVENT_SUPL_NOTIFY_VERIFY_REQ;
614    supl_req = &ni_req->payload.rpc_loc_ni_event_payload_u_type_u.supl_req;
615
616    // Encodings for Spirent Communications
617    char client_name[80]  = {0x53,0x78,0x5A,0x5E,0x76,0xD3,0x41,0xC3,0x77,
618            0xBB,0x5D,0x77,0xA7,0xC7,0x61,0x7A,0xFA,0xED,0x9E,0x03};
619    char requestor_id[80] = {0x53,0x78,0x5A,0x5E,0x76,0xD3,0x41,0xC3,0x77,
620            0xBB,0x5D,0x77,0xA7,0xC7,0x61,0x7A,0xFA,0xED,0x9E,0x03};
621
622    supl_req->flags = RPC_LOC_NI_CLIENT_NAME_PRESENT |
623                      RPC_LOC_NI_REQUESTOR_ID_PRESENT |
624                      RPC_LOC_NI_ENCODING_TYPE_PRESENT;
625
626    supl_req->datacoding_scheme = RPC_LOC_NI_SUPL_GSM_DEFAULT;
627
628    supl_req->client_name.data_coding_scheme = RPC_LOC_NI_SUPL_GSM_DEFAULT; // no coding
629    supl_req->client_name.client_name_string.client_name_string_len = strlen(client_name);
630    supl_req->client_name.client_name_string.client_name_string_val = client_name;
631    supl_req->client_name.string_len = strlen(client_name);
632
633    supl_req->requestor_id.data_coding_scheme = RPC_LOC_NI_SUPL_GSM_DEFAULT;
634    supl_req->requestor_id.requestor_id_string.requestor_id_string_len = strlen(requestor_id);
635    supl_req->requestor_id.requestor_id_string.requestor_id_string_val = requestor_id;
636    supl_req->requestor_id.string_len = strlen(requestor_id);
637
638    supl_req->notification_priv_type = RPC_LOC_NI_USER_NOTIFY_VERIFY_ALLOW_NO_RESP;
639    supl_req->user_response_timer = 10;
640
641    loc_event_cb(client_handle, loc_event, &payload);
642
643    busy = 0;
644
645    return NULL;
646}
647#endif // DEBUG_MOCK_NI
648
649/*===========================================================================
650FUNCTION    loc_event_cb
651
652DESCRIPTION
653   This is the callback function registered by loc_open.
654
655DEPENDENCIES
656   N/A
657
658RETURN VALUE
659   RPC_LOC_API_SUCCESS
660
661SIDE EFFECTS
662   N/A
663
664===========================================================================*/
665static int32 loc_event_cb(
666    rpc_loc_client_handle_type           client_handle,
667    rpc_loc_event_mask_type              loc_event,
668    const rpc_loc_event_payload_u_type*  loc_event_payload
669    )
670{
671    LOGV ("loc_event_cb, client = %d, loc_event = 0x%x", (int32) client_handle, (uint32) loc_event);
672    if (client_handle == loc_eng_data.client_handle)
673    {
674        pthread_mutex_lock(&loc_eng_data.deferred_action_mutex);
675        loc_eng_data.loc_event = loc_event;
676        memcpy(&loc_eng_data.loc_event_payload, loc_event_payload, sizeof(*loc_event_payload));
677
678        pthread_cond_signal  (&loc_eng_data.deferred_action_cond);
679        pthread_mutex_unlock (&loc_eng_data.deferred_action_mutex);
680    }
681    else
682    {
683        LOGD ("loc client mismatch: received = %d, expected = %d \n", (int32) client_handle, (int32) loc_eng_data.client_handle);
684    }
685
686    return RPC_LOC_API_SUCCESS;
687}
688
689/*===========================================================================
690FUNCTION    loc_eng_report_position
691
692DESCRIPTION
693   Reports position information to the Java layer.
694
695DEPENDENCIES
696   N/A
697
698RETURN VALUE
699   N/A
700
701SIDE EFFECTS
702   N/A
703
704===========================================================================*/
705static void loc_eng_report_position (const rpc_loc_parsed_position_s_type *location_report_ptr)
706{
707    GpsLocation location;
708
709    LOGV ("loc_eng_report_position: location report, valid mask = 0x%x, sess status = %d\n",
710         (uint32) location_report_ptr->valid_mask, location_report_ptr->session_status);
711
712    memset (&location, 0, sizeof(location));
713    location.size = sizeof(location);
714    if (location_report_ptr->valid_mask & RPC_LOC_POS_VALID_SESSION_STATUS)
715    {
716        // Not a position report, return
717        if (location_report_ptr->session_status == RPC_LOC_SESS_STATUS_SUCCESS)
718        {
719            if (location_report_ptr->valid_mask & RPC_LOC_POS_VALID_TIMESTAMP_UTC)
720            {
721                location.timestamp = location_report_ptr->timestamp_utc;
722            }
723
724            if ((location_report_ptr->valid_mask & RPC_LOC_POS_VALID_LATITUDE) &&
725                (location_report_ptr->valid_mask & RPC_LOC_POS_VALID_LONGITUDE))
726            {
727                location.flags    |= GPS_LOCATION_HAS_LAT_LONG;
728                location.latitude  = location_report_ptr->latitude;
729                location.longitude = location_report_ptr->longitude;
730            }
731
732            if (location_report_ptr->valid_mask &  RPC_LOC_POS_VALID_ALTITUDE_WRT_ELLIPSOID )
733            {
734                location.flags    |= GPS_LOCATION_HAS_ALTITUDE;
735                location.altitude = location_report_ptr->altitude_wrt_ellipsoid;
736            }
737
738            if ((location_report_ptr->valid_mask & RPC_LOC_POS_VALID_SPEED_HORIZONTAL) &&
739                (location_report_ptr->valid_mask & RPC_LOC_POS_VALID_SPEED_VERTICAL))
740            {
741                location.flags    |= GPS_LOCATION_HAS_SPEED;
742                location.speed = sqrt(location_report_ptr->speed_horizontal * location_report_ptr->speed_horizontal +
743                                     location_report_ptr->speed_vertical * location_report_ptr->speed_vertical);
744            }
745
746            if (location_report_ptr->valid_mask &  RPC_LOC_POS_VALID_HEADING)
747            {
748                location.flags    |= GPS_LOCATION_HAS_BEARING;
749                location.bearing = location_report_ptr->heading;
750            }
751
752            if (location_report_ptr->valid_mask & RPC_LOC_POS_VALID_HOR_UNC_CIRCULAR)
753            {
754                location.flags    |= GPS_LOCATION_HAS_ACCURACY;
755                location.accuracy = location_report_ptr->hor_unc_circular;
756            }
757
758            if (loc_eng_data.location_cb != NULL)
759            {
760                LOGV ("loc_eng_report_position: fire callback\n");
761                loc_eng_data.location_cb (&location);
762            }
763        }
764        else
765        {
766            LOGV ("loc_eng_report_position: ignore position report when session status = %d\n", location_report_ptr->session_status);
767        }
768    }
769    else
770    {
771        LOGV ("loc_eng_report_position: ignore position report when session status is not set\n");
772    }
773}
774
775/*===========================================================================
776FUNCTION    loc_eng_report_sv
777
778DESCRIPTION
779   Reports GPS satellite information to the Java layer.
780
781DEPENDENCIES
782   N/A
783
784RETURN VALUE
785   N/A
786
787SIDE EFFECTS
788   N/A
789
790===========================================================================*/
791static void loc_eng_report_sv (const rpc_loc_gnss_info_s_type *gnss_report_ptr)
792{
793    GpsSvStatus     SvStatus;
794    int             num_svs_max, i;
795	const rpc_loc_sv_info_s_type *sv_info_ptr;
796
797    LOGV ("loc_eng_report_sv: valid_mask = 0x%x, num of sv = %d\n",
798            (uint32) gnss_report_ptr->valid_mask,
799            gnss_report_ptr->sv_count);
800
801    num_svs_max = 0;
802    memset (&SvStatus, 0, sizeof (GpsSvStatus));
803    if (gnss_report_ptr->valid_mask & RPC_LOC_GNSS_INFO_VALID_SV_COUNT)
804    {
805        num_svs_max = gnss_report_ptr->sv_count;
806        if (num_svs_max > GPS_MAX_SVS)
807        {
808            num_svs_max = GPS_MAX_SVS;
809        }
810    }
811
812    if (gnss_report_ptr->valid_mask & RPC_LOC_GNSS_INFO_VALID_SV_LIST)
813    {
814        SvStatus.num_svs = 0;
815
816        for (i = 0; i < num_svs_max; i++)
817        {
818            sv_info_ptr = &(gnss_report_ptr->sv_list.sv_list_val[i]);
819            if (sv_info_ptr->valid_mask & RPC_LOC_SV_INFO_VALID_SYSTEM)
820            {
821                if (sv_info_ptr->system == RPC_LOC_SV_SYSTEM_GPS)
822                {
823                    SvStatus.sv_list[SvStatus.num_svs].size = sizeof(GpsSvStatus);
824                    SvStatus.sv_list[SvStatus.num_svs].prn = sv_info_ptr->prn;
825
826                    // We only have the data field to report gps eph and alm mask
827                    if ((sv_info_ptr->valid_mask & RPC_LOC_SV_INFO_VALID_HAS_EPH) &&
828                        (sv_info_ptr->has_eph == 1))
829                    {
830                        SvStatus.ephemeris_mask |= (1 << (sv_info_ptr->prn-1));
831                    }
832
833                    if ((sv_info_ptr->valid_mask & RPC_LOC_SV_INFO_VALID_HAS_ALM) &&
834                        (sv_info_ptr->has_alm == 1))
835                    {
836                        SvStatus.almanac_mask |= (1 << (sv_info_ptr->prn-1));
837                    }
838
839                    if ((sv_info_ptr->valid_mask & RPC_LOC_SV_INFO_VALID_PROCESS_STATUS) &&
840                        (sv_info_ptr->process_status == RPC_LOC_SV_STATUS_TRACK))
841                    {
842                        SvStatus.used_in_fix_mask |= (1 << (sv_info_ptr->prn-1));
843                    }
844                }
845                // SBAS: GPS RPN: 120-151,
846                // In exteneded measurement report, we follow nmea standard, which is from 33-64.
847                else if (sv_info_ptr->system == RPC_LOC_SV_SYSTEM_SBAS)
848                {
849                    SvStatus.sv_list[SvStatus.num_svs].prn = sv_info_ptr->prn + 33 - 120;
850                }
851                // Gloness: Slot id: 1-32
852                // In extended measurement report, we follow nmea standard, which is 65-96
853                else if (sv_info_ptr->system == RPC_LOC_SV_SYSTEM_GLONASS)
854                {
855                    SvStatus.sv_list[SvStatus.num_svs].prn = sv_info_ptr->prn + (65-1);
856                }
857                // Unsupported SV system
858                else
859                {
860                    continue;
861                }
862            }
863
864            if (sv_info_ptr->valid_mask & RPC_LOC_SV_INFO_VALID_SNR)
865            {
866                SvStatus.sv_list[SvStatus.num_svs].snr = sv_info_ptr->snr;
867            }
868
869            if (sv_info_ptr->valid_mask & RPC_LOC_SV_INFO_VALID_ELEVATION)
870            {
871                SvStatus.sv_list[SvStatus.num_svs].elevation = sv_info_ptr->elevation;
872            }
873
874            if (sv_info_ptr->valid_mask & RPC_LOC_SV_INFO_VALID_AZIMUTH)
875            {
876                SvStatus.sv_list[SvStatus.num_svs].azimuth = sv_info_ptr->azimuth;
877            }
878
879            SvStatus.num_svs++;
880        }
881    }
882
883    LOGV ("num_svs = %d, eph mask = %d, alm mask = %d\n", SvStatus.num_svs, SvStatus.ephemeris_mask, SvStatus.almanac_mask );
884    if ((SvStatus.num_svs != 0) && (loc_eng_data.sv_status_cb != NULL))
885    {
886        loc_eng_data.sv_status_cb(&SvStatus);
887    }
888}
889
890/*===========================================================================
891FUNCTION    loc_eng_report_status
892
893DESCRIPTION
894   Reports GPS engine state to Java layer.
895
896DEPENDENCIES
897   N/A
898
899RETURN VALUE
900   N/A
901
902SIDE EFFECTS
903   N/A
904
905===========================================================================*/
906static void loc_eng_report_status (const rpc_loc_status_event_s_type *status_report_ptr)
907{
908    GpsStatus status;
909
910    LOGV ("loc_eng_report_status: event = %d\n", status_report_ptr->event);
911
912    memset (&status, 0, sizeof(status));
913    status.size = sizeof(status);
914    status.status = GPS_STATUS_NONE;
915    if (status_report_ptr->event == RPC_LOC_STATUS_EVENT_ENGINE_STATE)
916    {
917        if (status_report_ptr->payload.rpc_loc_status_event_payload_u_type_u.engine_state == RPC_LOC_ENGINE_STATE_ON)
918        {
919            // GPS_STATUS_SESSION_BEGIN implies GPS_STATUS_ENGINE_ON
920            status.status = GPS_STATUS_SESSION_BEGIN;
921            loc_eng_data.status_cb (&status);
922        }
923        else if (status_report_ptr->payload.rpc_loc_status_event_payload_u_type_u.engine_state == RPC_LOC_ENGINE_STATE_OFF)
924        {
925            // GPS_STATUS_SESSION_END implies GPS_STATUS_ENGINE_OFF
926            status.status = GPS_STATUS_ENGINE_OFF;
927            loc_eng_data.status_cb (&status);
928        }
929    }
930
931    pthread_mutex_lock (&loc_eng_data.deferred_action_mutex);
932    loc_eng_data.engine_status = status.status;
933
934    // Wake up the thread for aiding data deletion.
935    if ((loc_eng_data.engine_status != GPS_STATUS_SESSION_BEGIN) &&
936        (loc_eng_data.aiding_data_for_deletion != 0))
937    {
938        pthread_cond_signal(&(loc_eng_data.deferred_action_cond));
939        // In case gps engine is ON, the assistance data will be deleted when the engine is OFF
940    }
941
942    pthread_mutex_unlock (&loc_eng_data.deferred_action_mutex);
943}
944
945static void loc_eng_report_nmea (const rpc_loc_nmea_report_s_type *nmea_report_ptr)
946{
947    if (loc_eng_data.nmea_cb != NULL)
948    {
949        struct timeval tv;
950
951        gettimeofday(&tv, (struct timezone *) NULL);
952        long long now = tv.tv_sec * 1000LL + tv.tv_usec / 1000;
953
954        loc_eng_data.nmea_cb(now, nmea_report_ptr->nmea_sentences.nmea_sentences_val,
955                nmea_report_ptr->nmea_sentences.nmea_sentences_len);
956    }
957}
958
959/*===========================================================================
960FUNCTION    loc_eng_process_conn_request
961
962DESCRIPTION
963   Requests data connection to be brought up/tore down with the location server.
964
965DEPENDENCIES
966   N/A
967
968RETURN VALUE
969   N/A
970
971SIDE EFFECTS
972   N/A
973
974===========================================================================*/
975static void loc_eng_process_conn_request (const rpc_loc_server_request_s_type *server_request_ptr)
976{
977    LOGD ("loc_event_cb: get loc event location server request, event = %d\n", server_request_ptr->event);
978
979    // Signal DeferredActionThread to send the APN name
980    pthread_mutex_lock(&loc_eng_data.deferred_action_mutex);
981
982    // This implemenation is based on the fact that modem now at any time has only one data connection for AGPS at any given time
983    if (server_request_ptr->event == RPC_LOC_SERVER_REQUEST_OPEN)
984    {
985        loc_eng_data.conn_handle = server_request_ptr->payload.rpc_loc_server_request_u_type_u.open_req.conn_handle;
986        loc_eng_data.agps_status = GPS_REQUEST_AGPS_DATA_CONN;
987    }
988    else
989    {
990        loc_eng_data.conn_handle = server_request_ptr->payload.rpc_loc_server_request_u_type_u.close_req.conn_handle;
991        loc_eng_data.agps_status = GPS_RELEASE_AGPS_DATA_CONN;
992    }
993
994    pthread_cond_signal  (&loc_eng_data.deferred_action_cond);
995    pthread_mutex_unlock (&loc_eng_data.deferred_action_mutex);
996}
997
998/*===========================================================================
999FUNCTION    loc_eng_agps_init
1000
1001DESCRIPTION
1002
1003
1004DEPENDENCIES
1005   NONE
1006
1007RETURN VALUE
1008   0
1009
1010SIDE EFFECTS
1011   N/A
1012
1013===========================================================================*/
1014static void loc_eng_agps_init(AGpsCallbacks* callbacks)
1015{
1016    LOGV("loc_eng_agps_init\n");
1017    loc_eng_data.agps_status_cb = callbacks->status_cb;
1018}
1019
1020static int loc_eng_agps_data_conn_open(const char* apn)
1021{
1022    int apn_len;
1023    LOGD("loc_eng_agps_data_conn_open: %s\n", apn);
1024
1025    pthread_mutex_lock(&(loc_eng_data.deferred_action_mutex));
1026    loc_eng_data.data_connection_succeeded = TRUE;
1027
1028    if (apn != NULL)
1029    {
1030        apn_len = strlen (apn);
1031
1032        if (apn_len >= sizeof(loc_eng_data.apn_name))
1033        {
1034            LOGD ("loc_eng_set_apn: error, apn name exceeds maximum lenght of 100 chars\n");
1035            apn_len = sizeof(loc_eng_data.apn_name) - 1;
1036        }
1037
1038        memcpy (loc_eng_data.apn_name, apn, apn_len);
1039        loc_eng_data.apn_name[apn_len] = '\0';
1040    }
1041
1042    pthread_cond_signal(&(loc_eng_data.deferred_action_cond));
1043    pthread_mutex_unlock(&(loc_eng_data.deferred_action_mutex));
1044    return 0;
1045}
1046
1047static int loc_eng_agps_data_conn_closed()
1048{
1049    LOGD("loc_eng_agps_data_conn_closed\n");
1050    pthread_mutex_lock(&(loc_eng_data.deferred_action_mutex));
1051    loc_eng_data.data_connection_closed = TRUE;
1052// DO WE NEED TO SIGNAL HERE?
1053    pthread_cond_signal(&(loc_eng_data.deferred_action_cond));
1054    pthread_mutex_unlock(&(loc_eng_data.deferred_action_mutex));
1055    return 0;
1056}
1057
1058static int loc_eng_agps_data_conn_failed()
1059{
1060    LOGD("loc_eng_agps_data_conn_failed\n");
1061
1062    pthread_mutex_lock(&(loc_eng_data.deferred_action_mutex));
1063    loc_eng_data.data_connection_failed = TRUE;
1064    pthread_cond_signal(&(loc_eng_data.deferred_action_cond));
1065    pthread_mutex_unlock(&(loc_eng_data.deferred_action_mutex));
1066    return 0;
1067}
1068
1069static int set_agps_server()
1070{
1071    rpc_loc_ioctl_data_u_type       ioctl_data;
1072    rpc_loc_server_info_s_type      *server_info_ptr;
1073    boolean                         ret_val;
1074    uint16                          port_temp;
1075    char                            url[24];
1076    int                             len;
1077    unsigned char                   *b_ptr;
1078
1079    if (loc_eng_data.agps_server_host[0] == 0 || loc_eng_data.agps_server_port == 0)
1080        return -1;
1081
1082    if (loc_eng_data.agps_server_address == 0) {
1083        struct hostent* he = gethostbyname(loc_eng_data.agps_server_host);
1084        if (he)
1085            loc_eng_data.agps_server_address = *(uint32_t *)he->h_addr_list[0];
1086    }
1087    if (loc_eng_data.agps_server_address == 0)
1088        return -1;
1089
1090    b_ptr = (unsigned char*) (&loc_eng_data.agps_server_address);
1091    memset(url, 0, sizeof(url));
1092    snprintf(url, sizeof(url) - 1, "%d.%d.%d.%d:%d",
1093            (*(b_ptr + 0)  & 0x000000ff), (*(b_ptr+1) & 0x000000ff),
1094            (*(b_ptr + 2)  & 0x000000ff), (*(b_ptr+3) & 0x000000ff),
1095            (loc_eng_data.agps_server_port & (0x0000ffff)));
1096    len = strlen (url);
1097
1098    server_info_ptr = &(ioctl_data.rpc_loc_ioctl_data_u_type_u.server_addr);
1099    ioctl_data.disc = RPC_LOC_IOCTL_SET_UMTS_SLP_SERVER_ADDR;
1100    server_info_ptr->addr_type = RPC_LOC_SERVER_ADDR_URL;
1101    server_info_ptr->addr_info.disc =  RPC_LOC_SERVER_ADDR_URL;
1102    server_info_ptr->addr_info.rpc_loc_server_addr_u_type_u.url.length = len;
1103    server_info_ptr->addr_info.rpc_loc_server_addr_u_type_u.url.addr.addr_val = url;
1104    server_info_ptr->addr_info.rpc_loc_server_addr_u_type_u.url.addr.addr_len= len;
1105
1106    LOGD ("set_agps_server, addr = %s\n", server_info_ptr->addr_info.rpc_loc_server_addr_u_type_u.url.addr.addr_val);
1107
1108    ret_val = loc_eng_ioctl (loc_eng_data.client_handle,
1109                            RPC_LOC_IOCTL_SET_UMTS_SLP_SERVER_ADDR,
1110                            &ioctl_data,
1111                            LOC_IOCTL_DEFAULT_TIMEOUT,
1112                            NULL /* No output information is expected*/);
1113
1114    if (ret_val != TRUE)
1115    {
1116        LOGD ("set_agps_server failed\n");
1117        return -1;
1118    }
1119    else
1120    {
1121        LOGV ("set_agps_server successful\n");
1122        return 0;
1123    }
1124}
1125
1126static int loc_eng_agps_set_server(AGpsType type, const char* hostname, int port)
1127{
1128    LOGD ("loc_eng_set_default_agps_server, type = %d, hostname = %s, port = %d\n", type, hostname, port);
1129
1130    if (type != AGPS_TYPE_SUPL)
1131        return -1;
1132
1133    strncpy(loc_eng_data.agps_server_host, hostname, sizeof(loc_eng_data.agps_server_host) - 1);
1134    loc_eng_data.agps_server_port = port;
1135    return 0;
1136}
1137
1138/*===========================================================================
1139FUNCTION    loc_eng_delete_aiding_data_deferred_action
1140
1141DESCRIPTION
1142   This is used to remove the aiding data when GPS engine is off.
1143
1144DEPENDENCIES
1145   Assumes the aiding data type specified in GpsAidingData matches with
1146   LOC API specification.
1147
1148RETURN VALUE
1149   RPC_LOC_API_SUCCESS
1150
1151SIDE EFFECTS
1152   N/A
1153
1154===========================================================================*/
1155static void loc_eng_delete_aiding_data_deferred_action (void)
1156{
1157    // Currently, we only support deletion of all aiding data,
1158    // since the Android defined aiding data mask matches with modem,
1159    // so just pass them down without any translation
1160    rpc_loc_ioctl_data_u_type          ioctl_data;
1161    rpc_loc_assist_data_delete_s_type  *assist_data_ptr;
1162    boolean                             ret_val;
1163
1164    ioctl_data.disc = RPC_LOC_IOCTL_DELETE_ASSIST_DATA;
1165
1166    assist_data_ptr = &(ioctl_data.rpc_loc_ioctl_data_u_type_u.assist_data_delete);
1167    if (loc_eng_data.aiding_data_for_deletion == GPS_DELETE_ALL)
1168    {
1169        assist_data_ptr->type = RPC_LOC_ASSIST_DATA_ALL;
1170    }
1171    else
1172    {
1173        assist_data_ptr->type = loc_eng_data.aiding_data_for_deletion;
1174    }
1175    memset (&(assist_data_ptr->reserved), 0, sizeof (assist_data_ptr->reserved));
1176
1177    ret_val = loc_eng_ioctl (loc_eng_data.client_handle,
1178                             RPC_LOC_IOCTL_DELETE_ASSIST_DATA ,
1179                             &ioctl_data,
1180                             LOC_IOCTL_DEFAULT_TIMEOUT,
1181                             NULL);
1182
1183    LOGD("loc_eng_ioctl for aiding data deletion returned %d, 1 for success\n", ret_val);
1184}
1185
1186/*===========================================================================
1187FUNCTION    loc_eng_process_atl_deferred_action
1188
1189DESCRIPTION
1190   This is used to inform the location engine of the processing status for
1191   data connection open/close request.
1192
1193DEPENDENCIES
1194   None
1195
1196RETURN VALUE
1197   RPC_LOC_API_SUCCESS
1198
1199SIDE EFFECTS
1200   N/A
1201
1202===========================================================================*/
1203static void loc_eng_process_atl_deferred_action (boolean data_connection_succeeded,
1204        boolean data_connection_closed)
1205{
1206    rpc_loc_server_open_status_s_type  *conn_open_status_ptr;
1207    rpc_loc_server_close_status_s_type *conn_close_status_ptr;
1208    rpc_loc_ioctl_data_u_type           ioctl_data;
1209    boolean                             ret_val;
1210    int                                 agps_status = -1;
1211
1212    LOGV("loc_eng_process_atl_deferred_action, agps_status = %d\n", loc_eng_data.agps_status);
1213
1214    memset (&ioctl_data, 0, sizeof (rpc_loc_ioctl_data_u_type));
1215
1216    if (data_connection_closed)
1217    {
1218        ioctl_data.disc = RPC_LOC_IOCTL_INFORM_SERVER_CLOSE_STATUS;
1219        conn_close_status_ptr = &(ioctl_data.rpc_loc_ioctl_data_u_type_u.conn_close_status);
1220        conn_close_status_ptr->conn_handle = loc_eng_data.conn_handle;
1221        conn_close_status_ptr->close_status = RPC_LOC_SERVER_CLOSE_SUCCESS;
1222    }
1223    else
1224    {
1225        ioctl_data.disc = RPC_LOC_IOCTL_INFORM_SERVER_OPEN_STATUS;
1226        conn_open_status_ptr = &ioctl_data.rpc_loc_ioctl_data_u_type_u.conn_open_status;
1227        conn_open_status_ptr->conn_handle = loc_eng_data.conn_handle;
1228        if (data_connection_succeeded)
1229        {
1230            conn_open_status_ptr->open_status = RPC_LOC_SERVER_OPEN_SUCCESS;
1231            // Both buffer are of the same maximum size, and the source is null terminated
1232            // strcpy (&(ioctl_data.rpc_loc_ioctl_data_u_type_u.conn_open_status.apn_name), &(loc_eng_data.apn_name));
1233            conn_open_status_ptr->apn_name = loc_eng_data.apn_name;
1234            // Delay this so that PDSM ATL module will behave properly
1235            sleep (1);
1236            LOGD("loc_eng_ioctl for ATL with apn_name = %s\n", conn_open_status_ptr->apn_name);
1237        }
1238        else // data_connection_failed
1239        {
1240            conn_open_status_ptr->open_status = RPC_LOC_SERVER_OPEN_FAIL;
1241        }
1242        // Delay this so that PDSM ATL module will behave properly
1243        sleep (1);
1244    }
1245
1246    ret_val = loc_eng_ioctl (loc_eng_data.client_handle,
1247                             ioctl_data.disc,
1248                             &ioctl_data,
1249                             LOC_IOCTL_DEFAULT_TIMEOUT,
1250                             NULL);
1251
1252    LOGD("loc_eng_ioctl for ATL returned %d (1 for success)\n", ret_val);
1253}
1254
1255/*===========================================================================
1256FUNCTION    loc_eng_process_loc_event
1257
1258DESCRIPTION
1259   This is used to process events received from the location engine.
1260
1261DEPENDENCIES
1262   None
1263
1264RETURN VALUE
1265   N/A
1266
1267SIDE EFFECTS
1268   N/A
1269
1270===========================================================================*/
1271static void loc_eng_process_loc_event (rpc_loc_event_mask_type loc_event,
1272        rpc_loc_event_payload_u_type* loc_event_payload)
1273{
1274    if (loc_event & RPC_LOC_EVENT_PARSED_POSITION_REPORT)
1275    {
1276        loc_eng_report_position (&(loc_event_payload->rpc_loc_event_payload_u_type_u.parsed_location_report));
1277    }
1278
1279    if (loc_event & RPC_LOC_EVENT_SATELLITE_REPORT)
1280    {
1281        loc_eng_report_sv (&(loc_event_payload->rpc_loc_event_payload_u_type_u.gnss_report));
1282    }
1283
1284    if (loc_event & RPC_LOC_EVENT_STATUS_REPORT)
1285    {
1286        loc_eng_report_status (&(loc_event_payload->rpc_loc_event_payload_u_type_u.status_report));
1287    }
1288
1289    if (loc_event & RPC_LOC_EVENT_NMEA_POSITION_REPORT)
1290    {
1291        loc_eng_report_nmea (&(loc_event_payload->rpc_loc_event_payload_u_type_u.nmea_report));
1292    }
1293
1294    // Android XTRA interface supports only XTRA download
1295    if (loc_event & RPC_LOC_EVENT_ASSISTANCE_DATA_REQUEST)
1296    {
1297        if (loc_event_payload->rpc_loc_event_payload_u_type_u.assist_data_request.event ==
1298                RPC_LOC_ASSIST_DATA_PREDICTED_ORBITS_REQ)
1299        {
1300            LOGD ("loc_event_cb: xtra download requst");
1301
1302            // Call Registered callback
1303            if (loc_eng_data.xtra_module_data.download_request_cb != NULL)
1304            {
1305                loc_eng_data.xtra_module_data.download_request_cb ();
1306            }
1307        }
1308    }
1309
1310    if (loc_event & RPC_LOC_EVENT_IOCTL_REPORT)
1311    {
1312        // Process the received RPC_LOC_EVENT_IOCTL_REPORT
1313        (void) loc_eng_ioctl_process_cb (loc_eng_data.client_handle,
1314                                &(loc_event_payload->rpc_loc_event_payload_u_type_u.ioctl_report));
1315    }
1316
1317    if (loc_event & RPC_LOC_EVENT_LOCATION_SERVER_REQUEST)
1318    {
1319        loc_eng_process_conn_request (&(loc_event_payload->rpc_loc_event_payload_u_type_u.loc_server_request));
1320    }
1321
1322    loc_eng_ni_callback(loc_event, loc_event_payload);
1323
1324#if DEBUG_MOCK_NI == 1
1325    // DEBUG only
1326    if ((loc_event & RPC_LOC_EVENT_STATUS_REPORT) &&
1327        loc_event_payload->rpc_loc_event_payload_u_type_u.status_report.
1328        payload.rpc_loc_status_event_payload_u_type_u.engine_state
1329        == RPC_LOC_ENGINE_STATE_OFF)
1330    {
1331        // Mock an NI request
1332        pthread_t th;
1333        pthread_create (&th, NULL, mock_ni, (void*) client_handle);
1334    }
1335#endif /* DEBUG_MOCK_NI == 1 */
1336}
1337
1338/*===========================================================================
1339FUNCTION loc_eng_process_deferred_action
1340
1341DESCRIPTION
1342   Main routine for the thread to execute certain commands
1343   that are not safe to be done from within an RPC callback.
1344
1345DEPENDENCIES
1346   None
1347
1348RETURN VALUE
1349   None
1350
1351SIDE EFFECTS
1352   N/A
1353
1354===========================================================================*/
1355static void* loc_eng_process_deferred_action (void* arg)
1356{
1357    AGpsStatus      status;
1358    status.size = sizeof(status);
1359    status.type = AGPS_TYPE_SUPL;
1360
1361    LOGD("loc_eng_process_deferred_action started\n");
1362
1363     // make sure we do not run in background scheduling group
1364     set_sched_policy(gettid(), SP_FOREGROUND);
1365
1366    // disable GPS lock
1367    loc_eng_set_gps_lock(RPC_LOC_LOCK_NONE);
1368
1369    while (loc_eng_data.deferred_action_thread_need_exit == FALSE)
1370    {
1371        GpsAidingData   aiding_data_for_deletion;
1372        GpsStatusValue  engine_status;
1373        boolean         data_connection_succeeded;
1374        boolean         data_connection_closed;
1375        boolean         data_connection_failed;
1376
1377        rpc_loc_event_mask_type         loc_event;
1378        rpc_loc_event_payload_u_type    loc_event_payload;
1379
1380        // Wait until we are signalled to do a deferred action, or exit
1381        pthread_mutex_lock(&loc_eng_data.deferred_action_mutex);
1382        pthread_cond_wait(&loc_eng_data.deferred_action_cond,
1383                            &loc_eng_data.deferred_action_mutex);
1384
1385        if (loc_eng_data.deferred_action_thread_need_exit == TRUE)
1386        {
1387            pthread_mutex_unlock(&loc_eng_data.deferred_action_mutex);
1388            break;
1389        }
1390
1391        // copy anything we need before releasing the mutex
1392        loc_event = loc_eng_data.loc_event;
1393        if (loc_event != 0) {
1394            memcpy(&loc_event_payload, &loc_eng_data.loc_event_payload, sizeof(loc_event_payload));
1395            loc_eng_data.loc_event = 0;
1396        }
1397
1398        engine_status = loc_eng_data.agps_status;
1399        aiding_data_for_deletion = loc_eng_data.aiding_data_for_deletion;
1400        status.status = loc_eng_data.agps_status;
1401        loc_eng_data.agps_status = 0;
1402        data_connection_succeeded = loc_eng_data.data_connection_succeeded;
1403        data_connection_closed = loc_eng_data.data_connection_closed;
1404        data_connection_failed = loc_eng_data.data_connection_failed;
1405        loc_eng_data.data_connection_closed = FALSE;
1406        loc_eng_data.data_connection_succeeded = FALSE;
1407        loc_eng_data.data_connection_failed = FALSE;
1408
1409        // perform all actions after releasing the mutex to avoid blocking RPCs from the ARM9
1410        pthread_mutex_unlock(&(loc_eng_data.deferred_action_mutex));
1411
1412        if (loc_event != 0) {
1413            loc_eng_process_loc_event(loc_event, &loc_event_payload);
1414        }
1415
1416        // send_delete_aiding_data must be done when GPS engine is off
1417        if ((engine_status != GPS_STATUS_SESSION_BEGIN) && (aiding_data_for_deletion != 0))
1418        {
1419            loc_eng_delete_aiding_data_deferred_action ();
1420        }
1421
1422        if (data_connection_succeeded || data_connection_closed || data_connection_failed)
1423        {
1424            loc_eng_process_atl_deferred_action(data_connection_succeeded, data_connection_closed);
1425        }
1426
1427        if (status.status != 0 && loc_eng_data.agps_status_cb) {
1428            loc_eng_data.agps_status_cb(&status);
1429        }
1430
1431    }
1432
1433    LOGD("loc_eng_process_deferred_action thread exiting\n");
1434    return NULL;
1435}
1436
1437// for gps.c
1438extern "C" const GpsInterface* get_gps_interface()
1439{
1440    return &sLocEngInterface;
1441}
1442