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