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