• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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