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 ===========================================================================*/
gps_get_hardware_interface()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
loc_eng_init(GpsCallbacks * callbacks)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 ===========================================================================*/
loc_eng_cleanup()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 ===========================================================================*/
loc_eng_start()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 ===========================================================================*/
loc_eng_stop()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
loc_eng_set_gps_lock(rpc_loc_lock_e_type lock_type)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 ===========================================================================*/
loc_eng_set_position_mode(GpsPositionMode mode,GpsPositionRecurrence recurrence,uint32_t min_interval,uint32_t preferred_accuracy,uint32_t preferred_time)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 ===========================================================================*/
loc_eng_inject_time(GpsUtcTime time,int64_t timeReference,int uncertainty)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
loc_eng_inject_location(double latitude,double longitude,float accuracy)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 ===========================================================================*/
loc_eng_delete_aiding_data(GpsAidingData f)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 ===========================================================================*/
loc_eng_get_extension(const char * name)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 ===========================================================================*/
mock_ni(void * arg)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 ===========================================================================*/
loc_event_cb(rpc_loc_client_handle_type client_handle,rpc_loc_event_mask_type loc_event,const rpc_loc_event_payload_u_type * loc_event_payload)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 ===========================================================================*/
loc_eng_report_position(const rpc_loc_parsed_position_s_type * location_report_ptr)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 ===========================================================================*/
loc_eng_report_sv(const rpc_loc_gnss_info_s_type * gnss_report_ptr)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 ===========================================================================*/
loc_eng_report_status(const rpc_loc_status_event_s_type * status_report_ptr)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
loc_eng_report_nmea(const rpc_loc_nmea_report_s_type * nmea_report_ptr)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 ===========================================================================*/
loc_eng_process_conn_request(const rpc_loc_server_request_s_type * server_request_ptr)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 ===========================================================================*/
loc_eng_agps_init(AGpsCallbacks * callbacks)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
loc_eng_agps_data_conn_open(const char * apn)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
loc_eng_agps_data_conn_closed()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
loc_eng_agps_data_conn_failed()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
set_agps_server()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
loc_eng_agps_set_server(AGpsType type,const char * hostname,int port)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 ===========================================================================*/
loc_eng_delete_aiding_data_deferred_action(void)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 ===========================================================================*/
loc_eng_process_atl_deferred_action(int flags)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 ===========================================================================*/
loc_eng_process_loc_event(rpc_loc_event_mask_type loc_event,rpc_loc_event_payload_u_type * loc_event_payload)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 ===========================================================================*/
loc_eng_process_deferred_action(void * arg)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
get_gps_interface()1534 extern "C" const GpsInterface* get_gps_interface()
1535 {
1536 return &sLocEngInterface;
1537 }
1538