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