Home | History | Annotate | Download | only in libloc_api
      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   -----------------------------------------------------------------------------
     11 Copyright (c) 2009, QUALCOMM USA, INC.
     12 
     13 All rights reserved.
     14 
     15 Redistribution 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 
     23 THIS 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
     67 static int  loc_eng_init(GpsCallbacks* callbacks);
     68 static int  loc_eng_start();
     69 static int  loc_eng_stop();
     70 static int  loc_eng_set_position_mode(GpsPositionMode mode, int fix_frequency);
     71 static void loc_eng_cleanup();
     72 static int  loc_eng_inject_time(GpsUtcTime time, int64_t timeReference, int uncertainty);
     73 static int  loc_eng_inject_location(double latitude, double longitude, float accuracy);
     74 static void loc_eng_delete_aiding_data (GpsAidingData f);
     75 static const void* loc_eng_get_extension(const char* name);
     76 
     77 // Function declarations for sLocEngAGpsInterface
     78 static void loc_eng_agps_init(AGpsCallbacks* callbacks);
     79 static int loc_eng_agps_data_conn_open(const char* apn);
     80 static int loc_eng_agps_data_conn_closed();
     81 static int loc_eng_agps_data_conn_failed();
     82 static int loc_eng_agps_set_server(AGpsType type, const char* hostname, int port);
     83 
     84 
     85 static 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);
     88 static void loc_eng_report_position (const rpc_loc_parsed_position_s_type *location_report_ptr);
     89 static void loc_eng_report_sv (const rpc_loc_gnss_info_s_type *gnss_report_ptr);
     90 static void loc_eng_report_status (const rpc_loc_status_event_s_type *status_report_ptr);
     91 static void loc_eng_report_nmea (const rpc_loc_nmea_report_s_type *nmea_report_ptr);
     92 static void loc_eng_process_conn_request (const rpc_loc_server_request_s_type *server_request_ptr);
     93 
     94 static void* loc_eng_process_deferred_action (void* arg);
     95 static void loc_eng_process_atl_deferred_action (boolean data_connection_succeeded,
     96         boolean data_connection_closed);
     97 static void loc_eng_delete_aiding_data_deferred_action (void);
     98 
     99 static int set_agps_server();
    100 
    101 // Defines the GpsInterface in gps.h
    102 static 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 
    115 static 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
    125 loc_eng_data_s_type loc_eng_data;
    126 
    127 /*===========================================================================
    128 FUNCTION    gps_get_hardware_interface
    129 
    130 DESCRIPTION
    131    Returns the GPS hardware interaface based on LOC API
    132    if GPS is enabled.
    133 
    134 DEPENDENCIES
    135    None
    136 
    137 RETURN VALUE
    138    0: success
    139 
    140 SIDE EFFECTS
    141    N/A
    142 
    143 ===========================================================================*/
    144 const 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 /*===========================================================================
    160 FUNCTION    loc_eng_init
    161 
    162 DESCRIPTION
    163    Initialize the location engine, this include setting up global datas
    164    and registers location engien with loc api service.
    165 
    166 DEPENDENCIES
    167    None
    168 
    169 RETURN VALUE
    170    0: success
    171 
    172 SIDE EFFECTS
    173    N/A
    174 
    175 ===========================================================================*/
    176 static 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 /*===========================================================================
    238 FUNCTION    loc_eng_cleanup
    239 
    240 DESCRIPTION
    241    Cleans location engine. The location client handle will be released.
    242 
    243 DEPENDENCIES
    244    None
    245 
    246 RETURN VALUE
    247    None
    248 
    249 SIDE EFFECTS
    250    N/A
    251 
    252 ===========================================================================*/
    253 static 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 /*===========================================================================
    283 FUNCTION    loc_eng_start
    284 
    285 DESCRIPTION
    286    Starts the tracking session
    287 
    288 DEPENDENCIES
    289    None
    290 
    291 RETURN VALUE
    292    0: success
    293 
    294 SIDE EFFECTS
    295    N/A
    296 
    297 ===========================================================================*/
    298 static 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 /*===========================================================================
    322 FUNCTION    loc_eng_stop
    323 
    324 DESCRIPTION
    325    Stops the tracking session
    326 
    327 DEPENDENCIES
    328    None
    329 
    330 RETURN VALUE
    331    0: success
    332 
    333 SIDE EFFECTS
    334    N/A
    335 
    336 ===========================================================================*/
    337 static 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 
    352 static 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 /*===========================================================================
    378 FUNCTION    loc_eng_set_position_mode
    379 
    380 DESCRIPTION
    381    Sets the mode and fix frequnecy (in seconds) for the tracking session.
    382 
    383 DEPENDENCIES
    384    None
    385 
    386 RETURN VALUE
    387    0: success
    388 
    389 SIDE EFFECTS
    390    N/A
    391 
    392 ===========================================================================*/
    393 static 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 /*===========================================================================
    441 FUNCTION    loc_eng_inject_time
    442 
    443 DESCRIPTION
    444    This is used by Java native function to do time injection.
    445 
    446 DEPENDENCIES
    447    None
    448 
    449 RETURN VALUE
    450    RPC_LOC_API_SUCCESS
    451 
    452 SIDE EFFECTS
    453    N/A
    454 
    455 ===========================================================================*/
    456 static 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 
    485 static int loc_eng_inject_location (double latitude, double longitude, float accuracy)
    486 {
    487     /* not yet implemented */
    488     return 0;
    489 }
    490 
    491 /*===========================================================================
    492 FUNCTION    loc_eng_delete_aiding_data
    493 
    494 DESCRIPTION
    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 
    500 DEPENDENCIES
    501    Assumes the aiding data type specified in GpsAidingData matches with
    502    LOC API specification.
    503 
    504 RETURN VALUE
    505    RPC_LOC_API_SUCCESS
    506 
    507 SIDE EFFECTS
    508    N/A
    509 
    510 ===========================================================================*/
    511 static 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 /*===========================================================================
    540 FUNCTION    loc_eng_get_extension
    541 
    542 DESCRIPTION
    543    Get the gps extension to support XTRA.
    544 
    545 DEPENDENCIES
    546    N/A
    547 
    548 RETURN VALUE
    549    The GPS extension interface.
    550 
    551 SIDE EFFECTS
    552    N/A
    553 
    554 ===========================================================================*/
    555 static 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 /*===========================================================================
    575 FUNCTION    mock_ni
    576 
    577 DESCRIPTION
    578    DEBUG tool: simulate an NI request
    579 
    580 DEPENDENCIES
    581    N/A
    582 
    583 RETURN VALUE
    584    None
    585 
    586 SIDE EFFECTS
    587    N/A
    588 
    589 ===========================================================================*/
    590 static 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 /*===========================================================================
    649 FUNCTION    loc_event_cb
    650 
    651 DESCRIPTION
    652    This is the callback function registered by loc_open.
    653 
    654 DEPENDENCIES
    655    N/A
    656 
    657 RETURN VALUE
    658    RPC_LOC_API_SUCCESS
    659 
    660 SIDE EFFECTS
    661    N/A
    662 
    663 ===========================================================================*/
    664 static 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 /*===========================================================================
    689 FUNCTION    loc_eng_report_position
    690 
    691 DESCRIPTION
    692    Reports position information to the Java layer.
    693 
    694 DEPENDENCIES
    695    N/A
    696 
    697 RETURN VALUE
    698    N/A
    699 
    700 SIDE EFFECTS
    701    N/A
    702 
    703 ===========================================================================*/
    704 static 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 /*===========================================================================
    774 FUNCTION    loc_eng_report_sv
    775 
    776 DESCRIPTION
    777    Reports GPS satellite information to the Java layer.
    778 
    779 DEPENDENCIES
    780    N/A
    781 
    782 RETURN VALUE
    783    N/A
    784 
    785 SIDE EFFECTS
    786    N/A
    787 
    788 ===========================================================================*/
    789 static 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 /*===========================================================================
    888 FUNCTION    loc_eng_report_status
    889 
    890 DESCRIPTION
    891    Reports GPS engine state to Java layer.
    892 
    893 DEPENDENCIES
    894    N/A
    895 
    896 RETURN VALUE
    897    N/A
    898 
    899 SIDE EFFECTS
    900    N/A
    901 
    902 ===========================================================================*/
    903 static 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 
    941 static 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 /*===========================================================================
    956 FUNCTION    loc_eng_process_conn_request
    957 
    958 DESCRIPTION
    959    Requests data connection to be brought up/tore down with the location server.
    960 
    961 DEPENDENCIES
    962    N/A
    963 
    964 RETURN VALUE
    965    N/A
    966 
    967 SIDE EFFECTS
    968    N/A
    969 
    970 ===========================================================================*/
    971 static 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 /*===========================================================================
    995 FUNCTION    loc_eng_agps_init
    996 
    997 DESCRIPTION
    998 
    999 
   1000 DEPENDENCIES
   1001    NONE
   1002 
   1003 RETURN VALUE
   1004    0
   1005 
   1006 SIDE EFFECTS
   1007    N/A
   1008 
   1009 ===========================================================================*/
   1010 static 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 
   1016 static 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 
   1043 static 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 
   1054 static 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 
   1065 static 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 
   1122 static 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 /*===========================================================================
   1135 FUNCTION    loc_eng_delete_aiding_data_deferred_action
   1136 
   1137 DESCRIPTION
   1138    This is used to remove the aiding data when GPS engine is off.
   1139 
   1140 DEPENDENCIES
   1141    Assumes the aiding data type specified in GpsAidingData matches with
   1142    LOC API specification.
   1143 
   1144 RETURN VALUE
   1145    RPC_LOC_API_SUCCESS
   1146 
   1147 SIDE EFFECTS
   1148    N/A
   1149 
   1150 ===========================================================================*/
   1151 static 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 /*===========================================================================
   1183 FUNCTION    loc_eng_process_atl_deferred_action
   1184 
   1185 DESCRIPTION
   1186    This is used to inform the location engine of the processing status for
   1187    data connection open/close request.
   1188 
   1189 DEPENDENCIES
   1190    None
   1191 
   1192 RETURN VALUE
   1193    RPC_LOC_API_SUCCESS
   1194 
   1195 SIDE EFFECTS
   1196    N/A
   1197 
   1198 ===========================================================================*/
   1199 static 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 /*===========================================================================
   1252 FUNCTION    loc_eng_process_loc_event
   1253 
   1254 DESCRIPTION
   1255    This is used to process events received from the location engine.
   1256 
   1257 DEPENDENCIES
   1258    None
   1259 
   1260 RETURN VALUE
   1261    N/A
   1262 
   1263 SIDE EFFECTS
   1264    N/A
   1265 
   1266 ===========================================================================*/
   1267 static 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 /*===========================================================================
   1335 FUNCTION loc_eng_process_deferred_action
   1336 
   1337 DESCRIPTION
   1338    Main routine for the thread to execute certain commands
   1339    that are not safe to be done from within an RPC callback.
   1340 
   1341 DEPENDENCIES
   1342    None
   1343 
   1344 RETURN VALUE
   1345    None
   1346 
   1347 SIDE EFFECTS
   1348    N/A
   1349 
   1350 ===========================================================================*/
   1351 static 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