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
62static int  loc_eng_init(GpsCallbacks* callbacks);
63static int  loc_eng_start();
64static int  loc_eng_stop();
65static int  loc_eng_set_position_mode(GpsPositionMode mode, GpsPositionRecurrence recurrence,
66            uint32_t min_interval, uint32_t preferred_accuracy, uint32_t preferred_time);
67static void loc_eng_cleanup();
68static int  loc_eng_inject_time(GpsUtcTime time, int64_t timeReference, int uncertainty);
69static int  loc_eng_inject_location(double latitude, double longitude, float accuracy);
70static void loc_eng_delete_aiding_data (GpsAidingData f);
71static const void* loc_eng_get_extension(const char* name);
72
73// Function declarations for sLocEngAGpsInterface
74static void loc_eng_agps_init(AGpsCallbacks* callbacks);
75static int loc_eng_agps_data_conn_open(const char* apn);
76static int loc_eng_agps_data_conn_closed();
77static int loc_eng_agps_data_conn_failed();
78static int loc_eng_agps_set_server(AGpsType type, const char* hostname, int port);
79
80
81static 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);
84static void loc_eng_report_position (const rpc_loc_parsed_position_s_type *location_report_ptr);
85static void loc_eng_report_sv (const rpc_loc_gnss_info_s_type *gnss_report_ptr);
86static void loc_eng_report_status (const rpc_loc_status_event_s_type *status_report_ptr);
87static void loc_eng_report_nmea (const rpc_loc_nmea_report_s_type *nmea_report_ptr);
88static void loc_eng_process_conn_request (const rpc_loc_server_request_s_type *server_request_ptr);
89
90static void loc_eng_process_deferred_action (void* arg);
91static void loc_eng_process_atl_deferred_action (int flags);
92static void loc_eng_delete_aiding_data_deferred_action (void);
93
94static int set_agps_server();
95
96// Defines the GpsInterface in gps.h
97static 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
111static 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
122loc_eng_data_s_type loc_eng_data;
123
124/*===========================================================================
125FUNCTION    gps_get_hardware_interface
126
127DESCRIPTION
128   Returns the GPS hardware interaface based on LOC API
129   if GPS is enabled.
130
131DEPENDENCIES
132   None
133
134RETURN VALUE
135   0: success
136
137SIDE EFFECTS
138   N/A
139
140===========================================================================*/
141const 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/*===========================================================================
157FUNCTION    loc_eng_init
158
159DESCRIPTION
160   Initialize the location engine, this include setting up global datas
161   and registers location engien with loc api service.
162
163DEPENDENCIES
164   None
165
166RETURN VALUE
167   0: success
168
169SIDE 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
177static 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/*===========================================================================
244FUNCTION    loc_eng_cleanup
245
246DESCRIPTION
247   Cleans location engine. The location client handle will be released.
248
249DEPENDENCIES
250   None
251
252RETURN VALUE
253   None
254
255SIDE EFFECTS
256   N/A
257
258===========================================================================*/
259static 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/*===========================================================================
295FUNCTION    loc_eng_start
296
297DESCRIPTION
298   Starts the tracking session
299
300DEPENDENCIES
301   None
302
303RETURN VALUE
304   0: success
305
306SIDE EFFECTS
307   N/A
308
309===========================================================================*/
310static 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/*===========================================================================
334FUNCTION    loc_eng_stop
335
336DESCRIPTION
337   Stops the tracking session
338
339DEPENDENCIES
340   None
341
342RETURN VALUE
343   0: success
344
345SIDE EFFECTS
346   N/A
347
348===========================================================================*/
349static 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
376static 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/*===========================================================================
402FUNCTION    loc_eng_set_position_mode
403
404DESCRIPTION
405   Sets the mode and fix frequency for the tracking session.
406
407DEPENDENCIES
408   None
409
410RETURN VALUE
411   0: success
412
413SIDE EFFECTS
414   N/A
415
416===========================================================================*/
417static 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/*===========================================================================
484FUNCTION    loc_eng_inject_time
485
486DESCRIPTION
487   This is used by Java native function to do time injection.
488
489DEPENDENCIES
490   None
491
492RETURN VALUE
493   RPC_LOC_API_SUCCESS
494
495SIDE EFFECTS
496   N/A
497
498===========================================================================*/
499static 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
528static int loc_eng_inject_location (double latitude, double longitude, float accuracy)
529{
530    /* not yet implemented */
531    return 0;
532}
533
534/*===========================================================================
535FUNCTION    loc_eng_delete_aiding_data
536
537DESCRIPTION
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
543DEPENDENCIES
544   Assumes the aiding data type specified in GpsAidingData matches with
545   LOC API specification.
546
547RETURN VALUE
548   RPC_LOC_API_SUCCESS
549
550SIDE EFFECTS
551   N/A
552
553===========================================================================*/
554static 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/*===========================================================================
577FUNCTION    loc_eng_get_extension
578
579DESCRIPTION
580   Get the gps extension to support XTRA.
581
582DEPENDENCIES
583   N/A
584
585RETURN VALUE
586   The GPS extension interface.
587
588SIDE EFFECTS
589   N/A
590
591===========================================================================*/
592static 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/*===========================================================================
612FUNCTION    mock_ni
613
614DESCRIPTION
615   DEBUG tool: simulate an NI request
616
617DEPENDENCIES
618   N/A
619
620RETURN VALUE
621   None
622
623SIDE EFFECTS
624   N/A
625
626===========================================================================*/
627static 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/*===========================================================================
686FUNCTION    loc_event_cb
687
688DESCRIPTION
689   This is the callback function registered by loc_open.
690
691DEPENDENCIES
692   N/A
693
694RETURN VALUE
695   RPC_LOC_API_SUCCESS
696
697SIDE EFFECTS
698   N/A
699
700===========================================================================*/
701static 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/*===========================================================================
729FUNCTION    loc_eng_report_position
730
731DESCRIPTION
732   Reports position information to the Java layer.
733
734DEPENDENCIES
735   N/A
736
737RETURN VALUE
738   N/A
739
740SIDE EFFECTS
741   N/A
742
743===========================================================================*/
744static 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/*===========================================================================
815FUNCTION    loc_eng_report_sv
816
817DESCRIPTION
818   Reports GPS satellite information to the Java layer.
819
820DEPENDENCIES
821   N/A
822
823RETURN VALUE
824   N/A
825
826SIDE EFFECTS
827   N/A
828
829===========================================================================*/
830static 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/*===========================================================================
930FUNCTION    loc_eng_report_status
931
932DESCRIPTION
933   Reports GPS engine state to Java layer.
934
935DEPENDENCIES
936   N/A
937
938RETURN VALUE
939   N/A
940
941SIDE EFFECTS
942   N/A
943
944===========================================================================*/
945static 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
987static 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/*===========================================================================
1006FUNCTION    loc_eng_process_conn_request
1007
1008DESCRIPTION
1009   Requests data connection to be brought up/tore down with the location server.
1010
1011DEPENDENCIES
1012   N/A
1013
1014RETURN VALUE
1015   N/A
1016
1017SIDE EFFECTS
1018   N/A
1019
1020===========================================================================*/
1021static 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/*===========================================================================
1050FUNCTION    loc_eng_agps_init
1051
1052DESCRIPTION
1053
1054
1055DEPENDENCIES
1056   NONE
1057
1058RETURN VALUE
1059   0
1060
1061SIDE EFFECTS
1062   N/A
1063
1064===========================================================================*/
1065static 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
1071static 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
1100static 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
1112static 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
1125static 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
1194static 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/*===========================================================================
1207FUNCTION    loc_eng_delete_aiding_data_deferred_action
1208
1209DESCRIPTION
1210   This is used to remove the aiding data when GPS engine is off.
1211
1212DEPENDENCIES
1213   Assumes the aiding data type specified in GpsAidingData matches with
1214   LOC API specification.
1215
1216RETURN VALUE
1217   RPC_LOC_API_SUCCESS
1218
1219SIDE EFFECTS
1220   N/A
1221
1222===========================================================================*/
1223static 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/*===========================================================================
1249FUNCTION    loc_eng_process_atl_deferred_action
1250
1251DESCRIPTION
1252   This is used to inform the location engine of the processing status for
1253   data connection open/close request.
1254
1255DEPENDENCIES
1256   None
1257
1258RETURN VALUE
1259   RPC_LOC_API_SUCCESS
1260
1261SIDE EFFECTS
1262   N/A
1263
1264===========================================================================*/
1265static 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/*===========================================================================
1323FUNCTION    loc_eng_process_loc_event
1324
1325DESCRIPTION
1326   This is used to process events received from the location engine.
1327
1328DEPENDENCIES
1329   None
1330
1331RETURN VALUE
1332   N/A
1333
1334SIDE EFFECTS
1335   N/A
1336
1337===========================================================================*/
1338static 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/*===========================================================================
1406FUNCTION loc_eng_process_deferred_action
1407
1408DESCRIPTION
1409   Main routine for the thread to execute certain commands
1410   that are not safe to be done from within an RPC callback.
1411
1412DEPENDENCIES
1413   None
1414
1415RETURN VALUE
1416   None
1417
1418SIDE EFFECTS
1419   N/A
1420
1421===========================================================================*/
1422static 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
1530extern "C" const GpsInterface* get_gps_interface()
1531{
1532    return &sLocEngInterface;
1533}
1534