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