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