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