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