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