summaryrefslogtreecommitdiffstats
path: root/gps/libloc_api_50001/loc_eng.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gps/libloc_api_50001/loc_eng.cpp')
-rw-r--r--gps/libloc_api_50001/loc_eng.cpp2150
1 files changed, 2150 insertions, 0 deletions
diff --git a/gps/libloc_api_50001/loc_eng.cpp b/gps/libloc_api_50001/loc_eng.cpp
new file mode 100644
index 0000000..97cd9cb
--- /dev/null
+++ b/gps/libloc_api_50001/loc_eng.cpp
@@ -0,0 +1,2150 @@
+/* Copyright (c) 2009-2012 Code Aurora Forum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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.
+ * * Neither the name of Code Aurora Forum, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+ *
+ */
+
+#define LOG_NDDEBUG 0
+#define LOG_TAG "LocSvc_eng"
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <math.h>
+#include <pthread.h>
+#include <arpa/inet.h>
+#include <netinet/in.h> /* struct sockaddr_in */
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <netdb.h>
+#include <time.h>
+
+#include "LocApiAdapter.h"
+
+#include <cutils/sched_policy.h>
+#include <utils/SystemClock.h>
+#include <utils/Log.h>
+#include <string.h>
+
+#include <loc_eng.h>
+#include <loc_eng_ni.h>
+#include <loc_eng_dmn_conn.h>
+#include <loc_eng_dmn_conn_handler.h>
+#include <loc_eng_msg.h>
+#include <loc_eng_msg_id.h>
+#include <msg_q.h>
+#include <loc.h>
+
+#include "log_util.h"
+#include "loc_eng_log.h"
+
+#define SUCCESS TRUE
+#define FAILURE FALSE
+
+static void loc_eng_deferred_action_thread(void* context);
+static void* loc_eng_create_msg_q();
+static void loc_eng_free_msg(void* msg);
+
+pthread_mutex_t LocEngContext::lock = PTHREAD_MUTEX_INITIALIZER;
+pthread_cond_t LocEngContext::cond = PTHREAD_COND_INITIALIZER;
+LocEngContext* LocEngContext::me = NULL;
+boolean gpsConfigAlreadyRead = false;
+
+loc_gps_cfg_s_type gps_conf;
+
+/* Parameter spec table */
+static loc_param_s_type loc_parameter_table[] =
+{
+ {"INTERMEDIATE_POS", &gps_conf.INTERMEDIATE_POS, NULL, 'n'},
+ {"ACCURACY_THRES", &gps_conf.ACCURACY_THRES, NULL, 'n'},
+ {"ENABLE_WIPER", &gps_conf.ENABLE_WIPER, NULL, 'n'},
+ {"SUPL_VER", &gps_conf.SUPL_VER, NULL, 'n'},
+ {"CAPABILITIES", &gps_conf.CAPABILITIES, NULL, 'n'},
+ {"GYRO_BIAS_RANDOM_WALK", &gps_conf.GYRO_BIAS_RANDOM_WALK, &gps_conf.GYRO_BIAS_RANDOM_WALK_VALID, 'f'},
+ {"ACCEL_RANDOM_WALK_SPECTRAL_DENSITY", &gps_conf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY, &gps_conf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY_VALID, 'f'},
+ {"ANGLE_RANDOM_WALK_SPECTRAL_DENSITY", &gps_conf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY, &gps_conf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY_VALID, 'f'},
+ {"RATE_RANDOM_WALK_SPECTRAL_DENSITY", &gps_conf.RATE_RANDOM_WALK_SPECTRAL_DENSITY, &gps_conf.RATE_RANDOM_WALK_SPECTRAL_DENSITY_VALID, 'f'},
+ {"VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY", &gps_conf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY, &gps_conf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY_VALID, 'f'},
+ {"SENSOR_ACCEL_BATCHES_PER_SEC", &gps_conf.SENSOR_ACCEL_BATCHES_PER_SEC, NULL, 'n'},
+ {"SENSOR_ACCEL_SAMPLES_PER_BATCH", &gps_conf.SENSOR_ACCEL_SAMPLES_PER_BATCH, NULL, 'n'},
+ {"SENSOR_GYRO_BATCHES_PER_SEC", &gps_conf.SENSOR_GYRO_BATCHES_PER_SEC, NULL, 'n'},
+ {"SENSOR_GYRO_SAMPLES_PER_BATCH", &gps_conf.SENSOR_GYRO_SAMPLES_PER_BATCH, NULL, 'n'},
+ {"SENSOR_ACCEL_BATCHES_PER_SEC_HIGH", &gps_conf.SENSOR_ACCEL_BATCHES_PER_SEC_HIGH, NULL, 'n'},
+ {"SENSOR_ACCEL_SAMPLES_PER_BATCH_HIGH", &gps_conf.SENSOR_ACCEL_SAMPLES_PER_BATCH_HIGH, NULL, 'n'},
+ {"SENSOR_GYRO_BATCHES_PER_SEC_HIGH", &gps_conf.SENSOR_GYRO_BATCHES_PER_SEC_HIGH, NULL, 'n'},
+ {"SENSOR_GYRO_SAMPLES_PER_BATCH_HIGH", &gps_conf.SENSOR_GYRO_SAMPLES_PER_BATCH_HIGH, NULL, 'n'},
+ {"SENSOR_CONTROL_MODE", &gps_conf.SENSOR_CONTROL_MODE, NULL, 'n'},
+ {"SENSOR_USAGE", &gps_conf.SENSOR_USAGE, NULL, 'n'},
+ {"SENSOR_ALGORITHM_CONFIG_MASK", &gps_conf.SENSOR_ALGORITHM_CONFIG_MASK, NULL, 'n'},
+ {"QUIPC_ENABLED", &gps_conf.QUIPC_ENABLED, NULL, 'n'},
+ {"LPP_PROFILE", &gps_conf.LPP_PROFILE, NULL, 'n'},
+};
+
+static void loc_default_parameters(void)
+{
+ /* defaults */
+ gps_conf.INTERMEDIATE_POS = 0;
+ gps_conf.ACCURACY_THRES = 0;
+ gps_conf.ENABLE_WIPER = 0;
+ gps_conf.SUPL_VER = 0x10000;
+ gps_conf.CAPABILITIES = 0x7;
+
+ gps_conf.GYRO_BIAS_RANDOM_WALK = 0;
+ gps_conf.SENSOR_ACCEL_BATCHES_PER_SEC = 2;
+ gps_conf.SENSOR_ACCEL_SAMPLES_PER_BATCH = 5;
+ gps_conf.SENSOR_GYRO_BATCHES_PER_SEC = 2;
+ gps_conf.SENSOR_GYRO_SAMPLES_PER_BATCH = 5;
+ gps_conf.SENSOR_ACCEL_BATCHES_PER_SEC_HIGH = 4;
+ gps_conf.SENSOR_ACCEL_SAMPLES_PER_BATCH_HIGH = 25;
+ gps_conf.SENSOR_GYRO_BATCHES_PER_SEC_HIGH = 4;
+ gps_conf.SENSOR_GYRO_SAMPLES_PER_BATCH_HIGH = 25;
+ gps_conf.SENSOR_CONTROL_MODE = 0; /* AUTO */
+ gps_conf.SENSOR_USAGE = 0; /* Enabled */
+ gps_conf.SENSOR_ALGORITHM_CONFIG_MASK = 0; /* INS Disabled = FALSE*/
+
+ /* Values MUST be set by OEMs in configuration for sensor-assisted
+ navigation to work. There are NO default values */
+ gps_conf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY = 0;
+ gps_conf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY = 0;
+ gps_conf.RATE_RANDOM_WALK_SPECTRAL_DENSITY = 0;
+ gps_conf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY = 0;
+
+ gps_conf.GYRO_BIAS_RANDOM_WALK_VALID = 0;
+ gps_conf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY_VALID = 0;
+ gps_conf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY_VALID = 0;
+ gps_conf.RATE_RANDOM_WALK_SPECTRAL_DENSITY_VALID = 0;
+ gps_conf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY_VALID = 0;
+
+ /* LTE Positioning Profile configuration is disable by default*/
+ gps_conf.LPP_PROFILE = 0;
+}
+
+LocEngContext::LocEngContext(gps_create_thread threadCreator) :
+ deferred_q((const void*)loc_eng_create_msg_q()),
+ //TODO: should we conditionally create ulp msg q?
+ ulp_q((const void*)loc_eng_create_msg_q()),
+ deferred_action_thread(threadCreator("loc_eng",loc_eng_deferred_action_thread, this)),
+ counter(0)
+{
+ LOC_LOGV("LocEngContext %d : %d pthread_id %ld\n",
+ getpid(), gettid(),
+ deferred_action_thread);
+}
+
+LocEngContext* LocEngContext::get(gps_create_thread threadCreator)
+{
+ pthread_mutex_lock(&lock);
+ // gonna need mutex protection here...
+ if (NULL == me) {
+ me = new LocEngContext(threadCreator);
+ }
+ me->counter++;
+
+ pthread_mutex_unlock(&lock);
+ return me;
+}
+
+void LocEngContext::drop()
+{
+ if (deferred_action_thread != pthread_self()) {
+ pthread_mutex_lock(&lock);
+ counter--;
+ if (counter == 0) {
+ loc_eng_msg *msg(new loc_eng_msg(this, LOC_ENG_MSG_QUIT));
+ msg_q_snd((void*)deferred_q, msg, loc_eng_free_msg);
+
+ // I am not sure if this is going to be hazardous. The calling thread
+ // might be blocked for a while, if the q is loaded. I am wondering
+ // if we should just dump all the msgs in the q upon QUIT.
+ pthread_cond_wait(&cond, &lock);
+
+ msg_q_destroy((void**)&deferred_q);
+ msg_q_destroy((void**)&ulp_q);
+ delete me;
+ me = NULL;
+ }
+ pthread_mutex_unlock(&lock);
+ } else {
+ LOC_LOGE("The HAL thread cannot free itself");
+ }
+}
+
+// 2nd half of init(), singled out for
+// modem restart to use.
+static int loc_eng_reinit(loc_eng_data_s_type &loc_eng_data);
+static void loc_eng_agps_reinit(loc_eng_data_s_type &loc_eng_data);
+
+static int loc_eng_set_server(loc_eng_data_s_type &loc_eng_data,
+ LocServerType type, const char *hostname, int port);
+// Internal functions
+static void loc_inform_gps_status(loc_eng_data_s_type &loc_eng_data,
+ GpsStatusValue status);
+static void loc_eng_report_status(loc_eng_data_s_type &loc_eng_data,
+ GpsStatusValue status);
+static void loc_eng_process_conn_request(loc_eng_data_s_type &loc_eng_data,
+ int connHandle, AGpsType agps_type);
+static void loc_eng_agps_close_status(loc_eng_data_s_type &loc_eng_data, int is_succ);
+static void loc_eng_handle_engine_down(loc_eng_data_s_type &loc_eng_data) ;
+static void loc_eng_handle_engine_up(loc_eng_data_s_type &loc_eng_data) ;
+static int loc_eng_set_privacy(loc_eng_data_s_type &loc_eng_data,
+ int8_t privacy_setting);
+
+static char extra_data[100];
+/*********************************************************************
+ * Initialization checking macros
+ *********************************************************************/
+#define STATE_CHECK(ctx, x, ret) \
+ if (!(ctx)) \
+ { \
+ /* Not intialized, abort */\
+ LOC_LOGE("%s: log_eng state error: %s", __func__, x); \
+ EXIT_LOG(%s, x); \
+ ret; \
+ }
+#define INIT_CHECK(ctx, ret) STATE_CHECK(ctx, "instance not initialized", ret)
+
+void loc_eng_msg_sender(void* loc_eng_data_p, void* msg)
+{
+ LocEngContext* loc_eng_context = (LocEngContext*)((loc_eng_data_s_type*)loc_eng_data_p)->context;
+ msg_q_snd((void*)loc_eng_context->deferred_q, msg, loc_eng_free_msg);
+}
+
+static void* loc_eng_create_msg_q()
+{
+ void* q = NULL;
+ if (eMSG_Q_SUCCESS != msg_q_init(&q)) {
+ LOC_LOGE("loc_eng_create_msg_q Q init failed.");
+ q = NULL;
+ }
+ return q;
+}
+
+static void loc_eng_free_msg(void* msg)
+{
+ delete (loc_eng_msg*)msg;
+}
+
+/*===========================================================================
+FUNCTION loc_eng_init
+
+DESCRIPTION
+ Initialize the location engine, this include setting up global datas
+ and registers location engien with loc api service.
+
+DEPENDENCIES
+ None
+
+RETURN VALUE
+ 0: success
+
+SIDE EFFECTS
+ N/A
+
+===========================================================================*/
+int loc_eng_init(loc_eng_data_s_type &loc_eng_data, LocCallbacks* callbacks,
+ LOC_API_ADAPTER_EVENT_MASK_T event,
+ void (*loc_external_msg_sender) (void*, void*))
+
+{
+ ENTRY_LOG_CALLFLOW();
+ if (NULL == callbacks || 0 == event) {
+ LOC_LOGE("loc_eng_init: bad parameters cb %p eMask %d", callbacks, event);
+ EXIT_LOG(%d, 0);
+ return NULL;
+ }
+
+ if (NULL != loc_eng_data.context) {
+ // Current loc_eng_cleanup keeps context initialized, so must enable
+ // here too.
+ loc_eng_set_privacy(loc_eng_data, 1);
+ }
+
+ STATE_CHECK((NULL == loc_eng_data.context),
+ "instance already initialized", return 0);
+
+ memset(&loc_eng_data, 0, sizeof (loc_eng_data));
+
+ // Create context (msg q + thread) (if not yet created)
+ // This will also parse gps.conf, if not done.
+ loc_eng_data.context = (void*)LocEngContext::get(callbacks->create_thread_cb);
+ if (NULL != callbacks->set_capabilities_cb) {
+ callbacks->set_capabilities_cb(gps_conf.CAPABILITIES);
+ }
+
+ // Save callbacks
+ loc_eng_data.location_cb = callbacks->location_cb;
+ loc_eng_data.sv_status_cb = callbacks->sv_status_cb;
+ loc_eng_data.status_cb = callbacks->status_cb;
+ loc_eng_data.nmea_cb = callbacks->nmea_cb;
+ loc_eng_data.acquire_wakelock_cb = callbacks->acquire_wakelock_cb;
+ loc_eng_data.release_wakelock_cb = callbacks->release_wakelock_cb;
+
+ loc_eng_data.intermediateFix = gps_conf.INTERMEDIATE_POS;
+
+ // initial states taken care of by the memset above
+ // loc_eng_data.engine_status -- GPS_STATUS_NONE;
+ // loc_eng_data.fix_session_status -- GPS_STATUS_NONE;
+ // loc_eng_data.mute_session_state -- LOC_MUTE_SESS_NONE;
+
+ LocEng locEngHandle(&loc_eng_data, event, loc_eng_data.acquire_wakelock_cb,
+ loc_eng_data.release_wakelock_cb, loc_eng_msg_sender, loc_external_msg_sender,
+ callbacks->location_ext_parser, callbacks->sv_ext_parser);
+ loc_eng_data.client_handle = LocApiAdapter::getLocApiAdapter(locEngHandle);
+
+ int ret_val =-1;
+ if (NULL == loc_eng_data.client_handle) {
+ // drop the context and declare failure
+ ((LocEngContext*)(loc_eng_data.context))->drop();
+ loc_eng_data.context = NULL;
+ } else {
+ LOC_LOGD("loc_eng_init created client, id = %p\n", loc_eng_data.client_handle);
+
+ // call reinit to send initialization messages
+ int tries = 30;
+ while (tries > 0 &&
+ LOC_API_ADAPTER_ERR_SUCCESS != (ret_val = loc_eng_reinit(loc_eng_data))) {
+ tries--;
+ LOC_LOGD("loc_eng_init client open failed, %d more tries", tries);
+ sleep(1);
+ }
+
+ if (LOC_API_ADAPTER_ERR_SUCCESS == ret_val) {
+ loc_eng_set_privacy(loc_eng_data, 1);
+ }
+ }
+
+ EXIT_LOG(%d, ret_val);
+ return ret_val;
+}
+
+static int loc_eng_reinit(loc_eng_data_s_type &loc_eng_data)
+{
+ ENTRY_LOG();
+ int ret_val = loc_eng_data.client_handle->reinit();
+
+ if (LOC_API_ADAPTER_ERR_SUCCESS == ret_val) {
+ LOC_LOGD("loc_eng_reinit reinit() successful");
+
+ loc_eng_msg_suple_version *supl_msg(new loc_eng_msg_suple_version(&loc_eng_data,
+ gps_conf.SUPL_VER));
+ msg_q_snd((void*)((LocEngContext*)(loc_eng_data.context))->deferred_q,
+ supl_msg, loc_eng_free_msg);
+
+ loc_eng_msg_lpp_config *lpp_msg(new loc_eng_msg_lpp_config(&loc_eng_data,
+ gps_conf.LPP_PROFILE));
+ msg_q_snd((void*)((LocEngContext*)(loc_eng_data.context))->deferred_q,
+ lpp_msg, loc_eng_free_msg);
+
+ loc_eng_msg_sensor_control_config *sensor_control_config_msg(
+ new loc_eng_msg_sensor_control_config(&loc_eng_data, gps_conf.SENSOR_USAGE));
+ msg_q_snd((void*)((LocEngContext*)(loc_eng_data.context))->deferred_q,
+ sensor_control_config_msg, loc_eng_free_msg);
+
+ /* Make sure at least one of the sensor property is specified by the user in the gps.conf file. */
+ if( gps_conf.GYRO_BIAS_RANDOM_WALK_VALID ||
+ gps_conf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY_VALID ||
+ gps_conf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY_VALID ||
+ gps_conf.RATE_RANDOM_WALK_SPECTRAL_DENSITY_VALID ||
+ gps_conf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY_VALID )
+ {
+ loc_eng_msg_sensor_properties *sensor_properties_msg(
+ new loc_eng_msg_sensor_properties(&loc_eng_data,
+ gps_conf.GYRO_BIAS_RANDOM_WALK_VALID,
+ gps_conf.GYRO_BIAS_RANDOM_WALK,
+ gps_conf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY_VALID,
+ gps_conf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY,
+ gps_conf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY_VALID,
+ gps_conf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY,
+ gps_conf.RATE_RANDOM_WALK_SPECTRAL_DENSITY_VALID,
+ gps_conf.RATE_RANDOM_WALK_SPECTRAL_DENSITY,
+ gps_conf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY_VALID,
+ gps_conf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY));
+ msg_q_snd((void*)((LocEngContext*)(loc_eng_data.context))->deferred_q,
+ sensor_properties_msg, loc_eng_free_msg);
+ }
+
+ loc_eng_msg_sensor_perf_control_config *sensor_perf_control_conf_msg(
+ new loc_eng_msg_sensor_perf_control_config(&loc_eng_data,
+ gps_conf.SENSOR_CONTROL_MODE,
+ gps_conf.SENSOR_ACCEL_SAMPLES_PER_BATCH,
+ gps_conf.SENSOR_ACCEL_BATCHES_PER_SEC,
+ gps_conf.SENSOR_GYRO_SAMPLES_PER_BATCH,
+ gps_conf.SENSOR_GYRO_BATCHES_PER_SEC,
+ gps_conf.SENSOR_ACCEL_SAMPLES_PER_BATCH_HIGH,
+ gps_conf.SENSOR_ACCEL_BATCHES_PER_SEC_HIGH,
+ gps_conf.SENSOR_GYRO_SAMPLES_PER_BATCH_HIGH,
+ gps_conf.SENSOR_GYRO_BATCHES_PER_SEC_HIGH,
+ gps_conf.SENSOR_ALGORITHM_CONFIG_MASK));
+ msg_q_snd((void*)((LocEngContext*)(loc_eng_data.context))->deferred_q,
+ sensor_perf_control_conf_msg, loc_eng_free_msg);
+ }
+
+ EXIT_LOG(%d, ret_val);
+ return ret_val;
+}
+
+/*===========================================================================
+FUNCTION loc_eng_cleanup
+
+DESCRIPTION
+ Cleans location engine. The location client handle will be released.
+
+DEPENDENCIES
+ None
+
+RETURN VALUE
+ None
+
+SIDE EFFECTS
+ N/A
+
+===========================================================================*/
+void loc_eng_cleanup(loc_eng_data_s_type &loc_eng_data)
+{
+ ENTRY_LOG_CALLFLOW();
+ INIT_CHECK(loc_eng_data.context, return);
+
+ // XTRA has no state, so we are fine with it.
+
+ // we need to check and clear NI
+#if 0
+ // we need to check and clear ATL
+ if (NULL != loc_eng_data.agnss_nif) {
+ delete loc_eng_data.agnss_nif;
+ loc_eng_data.agnss_nif = NULL;
+ }
+ if (NULL != loc_eng_data.internet_nif) {
+ delete loc_eng_data.internet_nif;
+ loc_eng_data.internet_nif = NULL;
+ }
+#endif
+ if (loc_eng_data.client_handle->isInSession())
+ {
+ LOC_LOGD("loc_eng_cleanup: fix not stopped. stop it now.");
+ loc_eng_stop(loc_eng_data);
+ }
+
+ loc_eng_set_privacy(loc_eng_data, 0);
+
+#if 0 // can't afford to actually clean up, for many reason.
+
+ ((LocEngContext*)(loc_eng_data.context))->drop();
+ loc_eng_data.context = NULL;
+
+ // De-initialize ulp
+ if (locEngUlpInf != NULL)
+ {
+ locEngUlpInf = NULL;
+ msg_q_destroy( &loc_eng_data.ulp_q);
+ }
+
+ if (loc_eng_data.client_handle != NULL)
+ {
+ LOC_LOGD("loc_eng_init: client opened. close it now.");
+ delete loc_eng_data.client_handle;
+ loc_eng_data.client_handle = NULL;
+ }
+
+#ifdef FEATURE_GNSS_BIT_API
+ {
+ char baseband[PROPERTY_VALUE_MAX];
+ property_get("ro.baseband", baseband, "msm");
+ if ((strcmp(baseband,"svlte2a") == 0))
+ {
+ loc_eng_dmn_conn_loc_api_server_unblock();
+ loc_eng_dmn_conn_loc_api_server_join();
+ }
+ }
+#endif /* FEATURE_GNSS_BIT_API */
+
+#endif
+
+ EXIT_LOG(%s, VOID_RET);
+}
+
+
+/*===========================================================================
+FUNCTION loc_eng_start
+
+DESCRIPTION
+ Starts the tracking session
+
+DEPENDENCIES
+ None
+
+RETURN VALUE
+ 0: success
+
+SIDE EFFECTS
+ N/A
+
+===========================================================================*/
+int loc_eng_start(loc_eng_data_s_type &loc_eng_data)
+{
+ ENTRY_LOG_CALLFLOW();
+ INIT_CHECK(loc_eng_data.context, return -1);
+
+ if((loc_eng_data.ulp_initialized == true) && (gps_conf.CAPABILITIES & ULP_CAPABILITY))
+ {
+ //Pass the start messgage to ULP if present & activated
+ loc_eng_msg *msg(new loc_eng_msg(&loc_eng_data, ULP_MSG_START_FIX));
+ msg_q_snd( (void*)((LocEngContext*)(loc_eng_data.context))->ulp_q,
+ msg, loc_eng_free_msg);
+ }else
+ {
+ loc_eng_msg *msg(new loc_eng_msg(&loc_eng_data, LOC_ENG_MSG_START_FIX));
+ msg_q_snd((void*)((LocEngContext*)(loc_eng_data.context))->deferred_q,
+ msg, loc_eng_free_msg);
+ }
+ EXIT_LOG(%d, 0);
+ return 0;
+}
+
+static int loc_eng_start_handler(loc_eng_data_s_type &loc_eng_data)
+{
+ ENTRY_LOG();
+ int ret_val = LOC_API_ADAPTER_ERR_SUCCESS;
+
+ if (!loc_eng_data.client_handle->isInSession()) {
+ ret_val = loc_eng_data.client_handle->startFix();
+
+ if (ret_val == LOC_API_ADAPTER_ERR_SUCCESS ||
+ ret_val == LOC_API_ADAPTER_ERR_ENGINE_DOWN)
+ {
+ loc_inform_gps_status(loc_eng_data, GPS_STATUS_SESSION_BEGIN);
+ loc_eng_data.client_handle->setInSession(TRUE);
+ }
+ }
+
+ EXIT_LOG(%d, ret_val);
+ return ret_val;
+}
+
+/*===========================================================================
+FUNCTION loc_eng_stop_wrapper
+
+DESCRIPTION
+ Stops the tracking session
+
+DEPENDENCIES
+ None
+
+RETURN VALUE
+ 0: success
+
+SIDE EFFECTS
+ N/A
+
+===========================================================================*/
+int loc_eng_stop(loc_eng_data_s_type &loc_eng_data)
+{
+ ENTRY_LOG_CALLFLOW();
+ INIT_CHECK(loc_eng_data.context, return -1);
+
+ if((loc_eng_data.ulp_initialized == true) && (gps_conf.CAPABILITIES & ULP_CAPABILITY))
+ {
+ //Pass the start messgage to ULP if present & activated
+ loc_eng_msg *msg(new loc_eng_msg(&loc_eng_data, ULP_MSG_STOP_FIX));
+ msg_q_snd( (void*)((LocEngContext*)(loc_eng_data.context))->ulp_q,
+ msg, loc_eng_free_msg);
+ }else
+ {
+ loc_eng_msg *msg(new loc_eng_msg(&loc_eng_data, LOC_ENG_MSG_STOP_FIX));
+ msg_q_snd((void*)((LocEngContext*)(loc_eng_data.context))->deferred_q,
+ msg, loc_eng_free_msg);
+ }
+
+ EXIT_LOG(%d, 0);
+ return 0;
+}
+
+static int loc_eng_stop_handler(loc_eng_data_s_type &loc_eng_data)
+{
+ ENTRY_LOG();
+ int ret_val = LOC_API_ADAPTER_ERR_SUCCESS;
+
+ if (loc_eng_data.client_handle->isInSession()) {
+
+ ret_val = loc_eng_data.client_handle->stopFix();
+ if (ret_val == LOC_API_ADAPTER_ERR_SUCCESS)
+ {
+ loc_inform_gps_status(loc_eng_data, GPS_STATUS_SESSION_END);
+ }
+
+ loc_eng_data.client_handle->setInSession(FALSE);
+ }
+
+ EXIT_LOG(%d, ret_val);
+ return ret_val;
+}
+
+/*===========================================================================
+FUNCTION loc_eng_mute_one_session
+
+DESCRIPTION
+ Mutes one session
+
+DEPENDENCIES
+ None
+
+RETURN VALUE
+ 0: Success
+
+SIDE EFFECTS
+ N/A
+
+===========================================================================*/
+void loc_eng_mute_one_session(loc_eng_data_s_type &loc_eng_data)
+{
+ ENTRY_LOG();
+ loc_eng_data.mute_session_state = LOC_MUTE_SESS_WAIT;
+ EXIT_LOG(%s, VOID_RET);
+}
+
+/*===========================================================================
+FUNCTION loc_eng_set_position_mode
+
+DESCRIPTION
+ Sets the mode and fix frequency for the tracking session.
+
+DEPENDENCIES
+ None
+
+RETURN VALUE
+ 0: success
+
+SIDE EFFECTS
+ N/A
+
+===========================================================================*/
+int loc_eng_set_position_mode(loc_eng_data_s_type &loc_eng_data,
+ LocPosMode &params)
+{
+ ENTRY_LOG_CALLFLOW();
+ INIT_CHECK(loc_eng_data.context, return -1);
+ loc_eng_msg_position_mode *msg(
+ new loc_eng_msg_position_mode(&loc_eng_data, params));
+ msg_q_snd((void*)((LocEngContext*)(loc_eng_data.context))->deferred_q,
+ msg, loc_eng_free_msg);
+
+ EXIT_LOG(%d, 0);
+ return 0;
+}
+
+/*===========================================================================
+FUNCTION loc_eng_inject_time
+
+DESCRIPTION
+ This is used by Java native function to do time injection.
+
+DEPENDENCIES
+ None
+
+RETURN VALUE
+ 0
+
+SIDE EFFECTS
+ N/A
+
+===========================================================================*/
+int loc_eng_inject_time(loc_eng_data_s_type &loc_eng_data, GpsUtcTime time,
+ int64_t timeReference, int uncertainty)
+{
+ ENTRY_LOG_CALLFLOW();
+ INIT_CHECK(loc_eng_data.context, return -1);
+ loc_eng_msg_set_time *msg(
+ new loc_eng_msg_set_time(&loc_eng_data,
+ time,
+ timeReference,
+ uncertainty));
+ msg_q_snd((void*)((LocEngContext*)(loc_eng_data.context))->deferred_q,
+ msg, loc_eng_free_msg);
+
+ EXIT_LOG(%d, 0);
+ return 0;
+}
+
+
+/*===========================================================================
+FUNCTION loc_eng_inject_location
+
+DESCRIPTION
+ This is used by Java native function to do location injection.
+
+DEPENDENCIES
+ None
+
+RETURN VALUE
+ 0 : Successful
+ error code : Failure
+
+SIDE EFFECTS
+ N/A
+===========================================================================*/
+int loc_eng_inject_location(loc_eng_data_s_type &loc_eng_data, double latitude,
+ double longitude, float accuracy)
+{
+ ENTRY_LOG_CALLFLOW();
+ INIT_CHECK(loc_eng_data.context, return -1);
+ loc_eng_msg_inject_location *msg(
+ new loc_eng_msg_inject_location(&loc_eng_data,
+ latitude,
+ longitude,
+ accuracy));
+ msg_q_snd((void*)((LocEngContext*)(loc_eng_data.context))->deferred_q,
+ msg, loc_eng_free_msg);
+
+ EXIT_LOG(%d, 0);
+ return 0;
+}
+
+
+/*===========================================================================
+FUNCTION loc_eng_delete_aiding_data
+
+DESCRIPTION
+ This is used by Java native function to delete the aiding data. The function
+ updates the global variable for the aiding data to be deleted. If the GPS
+ engine is off, the aiding data will be deleted. Otherwise, the actual action
+ will happen when gps engine is turned off.
+
+DEPENDENCIES
+ Assumes the aiding data type specified in GpsAidingData matches with
+ LOC API specification.
+
+RETURN VALUE
+ None
+
+SIDE EFFECTS
+ N/A
+
+===========================================================================*/
+void loc_eng_delete_aiding_data(loc_eng_data_s_type &loc_eng_data, GpsAidingData f)
+{
+ ENTRY_LOG_CALLFLOW();
+ INIT_CHECK(loc_eng_data.context, return);
+
+ loc_eng_msg_delete_aiding_data *msg(
+ new loc_eng_msg_delete_aiding_data(&loc_eng_data,
+ f));
+ msg_q_snd((void*)((LocEngContext*)(loc_eng_data.context))->deferred_q,
+ msg, loc_eng_free_msg);
+
+ EXIT_LOG(%s, VOID_RET);
+}
+
+/*===========================================================================
+
+FUNCTION loc_inform_gps_state
+
+DESCRIPTION
+ Informs the GPS Provider about the GPS status
+
+DEPENDENCIES
+ None
+
+RETURN VALUE
+ None
+
+SIDE EFFECTS
+ N/A
+
+===========================================================================*/
+static void loc_inform_gps_status(loc_eng_data_s_type &loc_eng_data, GpsStatusValue status)
+{
+ ENTRY_LOG();
+
+ static GpsStatusValue last_status = GPS_STATUS_NONE;
+
+ GpsStatus gs = { sizeof(gs),status };
+
+
+ if (loc_eng_data.status_cb)
+ {
+ CALLBACK_LOG_CALLFLOW("status_cb", %s, loc_get_gps_status_name(gs.status));
+ loc_eng_data.status_cb(&gs);
+ }
+
+ last_status = status;
+
+ EXIT_LOG(%s, VOID_RET);
+}
+
+/*===========================================================================
+FUNCTION loc_eng_agps_reinit
+
+DESCRIPTION
+ 2nd half of loc_eng_agps_init(), singled out for modem restart to use.
+
+DEPENDENCIES
+ NONE
+
+RETURN VALUE
+ 0
+
+SIDE EFFECTS
+ N/A
+
+===========================================================================*/
+static void loc_eng_agps_reinit(loc_eng_data_s_type &loc_eng_data)
+{
+ ENTRY_LOG();
+
+ // Set server addresses which came before init
+ if (loc_eng_data.supl_host_set)
+ {
+ loc_eng_set_server(loc_eng_data, LOC_AGPS_SUPL_SERVER,
+ loc_eng_data.supl_host_buf,
+ loc_eng_data.supl_port_buf);
+ }
+
+ if (loc_eng_data.c2k_host_set)
+ {
+ loc_eng_set_server(loc_eng_data, LOC_AGPS_CDMA_PDE_SERVER,
+ loc_eng_data.c2k_host_buf,
+ loc_eng_data.c2k_port_buf);
+ }
+ EXIT_LOG(%s, VOID_RET);
+}
+/*===========================================================================
+FUNCTION loc_eng_agps_init
+
+DESCRIPTION
+ Initialize the AGps interface.
+
+DEPENDENCIES
+ NONE
+
+RETURN VALUE
+ 0
+
+SIDE EFFECTS
+ N/A
+
+===========================================================================*/
+void loc_eng_agps_init(loc_eng_data_s_type &loc_eng_data, AGpsCallbacks* callbacks)
+{
+ ENTRY_LOG_CALLFLOW();
+ INIT_CHECK(loc_eng_data.context, return);
+ STATE_CHECK((NULL == loc_eng_data.agps_status_cb),
+ "agps instance already initialized",
+ return);
+ loc_eng_data.agps_status_cb = callbacks->status_cb;
+
+ loc_eng_data.agnss_nif = new AgpsStateMachine(loc_eng_data.agps_status_cb,
+ AGPS_TYPE_SUPL,
+ false);
+ loc_eng_data.internet_nif = new AgpsStateMachine(loc_eng_data.agps_status_cb,
+ AGPS_TYPE_WWAN_ANY,
+ false);
+ loc_eng_data.wifi_nif = new AgpsStateMachine(loc_eng_data.agps_status_cb,
+ AGPS_TYPE_WIFI,
+ true);
+
+#ifdef FEATURE_GNSS_BIT_API
+ {
+ char baseband[PROPERTY_VALUE_MAX];
+ property_get("ro.baseband", baseband, "msm");
+ if ((strcmp(baseband,"svlte2a") == 0) ||
+ (strcmp(baseband,"msm") == 0))
+ {
+ loc_eng_dmn_conn_loc_api_server_launch(callbacks->create_thread_cb,
+ NULL, NULL, &loc_eng_data);
+ }
+ }
+#endif /* FEATURE_GNSS_BIT_API */
+
+ loc_eng_agps_reinit(loc_eng_data);
+ EXIT_LOG(%s, VOID_RET);
+}
+
+/*===========================================================================
+FUNCTION loc_eng_agps_open
+
+DESCRIPTION
+ This function is called when on-demand data connection opening is successful.
+It should inform engine about the data open result.
+
+DEPENDENCIES
+ NONE
+
+RETURN VALUE
+ 0
+
+SIDE EFFECTS
+ N/A
+
+===========================================================================*/
+int loc_eng_agps_open(loc_eng_data_s_type &loc_eng_data, AGpsType agpsType,
+ const char* apn, AGpsBearerType bearerType)
+{
+ ENTRY_LOG_CALLFLOW();
+ INIT_CHECK(loc_eng_data.context && loc_eng_data.agps_status_cb,
+ return -1);
+
+ if (apn == NULL)
+ {
+ LOC_LOGE("APN Name NULL\n");
+ return 0;
+ }
+
+ LOC_LOGD("loc_eng_agps_open APN name = [%s]", apn);
+
+ int apn_len = smaller_of(strlen (apn), MAX_APN_LEN);
+ loc_eng_msg_atl_open_success *msg(
+ new loc_eng_msg_atl_open_success(&loc_eng_data, agpsType, apn,
+ apn_len, bearerType));
+ msg_q_snd((void*)((LocEngContext*)(loc_eng_data.context))->deferred_q,
+ msg, loc_eng_free_msg);
+
+ EXIT_LOG(%d, 0);
+ return 0;
+}
+
+/*===========================================================================
+FUNCTION loc_eng_agps_closed
+
+DESCRIPTION
+ This function is called when on-demand data connection closing is done.
+It should inform engine about the data close result.
+
+DEPENDENCIES
+ NONE
+
+RETURN VALUE
+ 0
+
+SIDE EFFECTS
+ N/A
+
+===========================================================================*/
+int loc_eng_agps_closed(loc_eng_data_s_type &loc_eng_data, AGpsType agpsType)
+{
+ ENTRY_LOG_CALLFLOW();
+ INIT_CHECK(loc_eng_data.context && loc_eng_data.agps_status_cb,
+ return -1);
+
+ loc_eng_msg_atl_closed *msg(new loc_eng_msg_atl_closed(&loc_eng_data, agpsType));
+ msg_q_snd((void*)((LocEngContext*)(loc_eng_data.context))->deferred_q,
+ msg, loc_eng_free_msg);
+
+ EXIT_LOG(%d, 0);
+ return 0;
+}
+
+/*===========================================================================
+FUNCTION loc_eng_agps_open_failed
+
+DESCRIPTION
+ This function is called when on-demand data connection opening has failed.
+It should inform engine about the data open result.
+
+DEPENDENCIES
+ NONE
+
+RETURN VALUE
+ 0
+
+SIDE EFFECTS
+ N/A
+
+===========================================================================*/
+int loc_eng_agps_open_failed(loc_eng_data_s_type &loc_eng_data, AGpsType agpsType)
+{
+ ENTRY_LOG_CALLFLOW();
+ INIT_CHECK(loc_eng_data.context && loc_eng_data.agps_status_cb,
+ return -1);
+
+ loc_eng_msg_atl_open_failed *msg(new loc_eng_msg_atl_open_failed(&loc_eng_data, agpsType));
+ msg_q_snd((void*)((LocEngContext*)(loc_eng_data.context))->deferred_q,
+ msg, loc_eng_free_msg);
+
+ EXIT_LOG(%d, 0);
+ return 0;
+}
+
+/*===========================================================================
+
+FUNCTION resolve_in_addr
+
+DESCRIPTION
+ Translates a hostname to in_addr struct
+
+DEPENDENCIES
+ n/a
+
+RETURN VALUE
+ TRUE if successful
+
+SIDE EFFECTS
+ n/a
+
+===========================================================================*/
+static boolean resolve_in_addr(const char *host_addr, struct in_addr *in_addr_ptr)
+{
+ ENTRY_LOG();
+ boolean ret_val = TRUE;
+
+ struct hostent *hp;
+ hp = gethostbyname(host_addr);
+ if (hp != NULL) /* DNS OK */
+ {
+ memcpy(in_addr_ptr, hp->h_addr_list[0], hp->h_length);
+ }
+ else
+ {
+ /* Try IP representation */
+ if (inet_aton(host_addr, in_addr_ptr) == 0)
+ {
+ /* IP not valid */
+ LOC_LOGE("DNS query on '%s' failed\n", host_addr);
+ ret_val = FALSE;
+ }
+ }
+
+ EXIT_LOG(%s, loc_logger_boolStr[ret_val!=0]);
+ return ret_val;
+}
+
+/*===========================================================================
+FUNCTION loc_eng_set_server
+
+DESCRIPTION
+ This is used to set the default AGPS server. Server address is obtained
+ from gps.conf.
+
+DEPENDENCIES
+ NONE
+
+RETURN VALUE
+ 0
+
+SIDE EFFECTS
+ N/A
+
+===========================================================================*/
+static int loc_eng_set_server(loc_eng_data_s_type &loc_eng_data,
+ LocServerType type, const char* hostname, int port)
+{
+ ENTRY_LOG();
+ int ret = 0;
+
+ if (LOC_AGPS_SUPL_SERVER == type) {
+ char url[MAX_URL_LEN];
+ unsigned int len = snprintf(url, sizeof(url), "%s:%u", hostname, (unsigned) port);
+
+ if (sizeof(url) > len) {
+ loc_eng_msg_set_server_url *msg(new loc_eng_msg_set_server_url(&loc_eng_data,
+ url, len));
+ msg_q_snd((void*)((LocEngContext*)(loc_eng_data.context))->deferred_q,
+ msg, loc_eng_free_msg);
+ }
+ } else if (LOC_AGPS_CDMA_PDE_SERVER == type ||
+ LOC_AGPS_CUSTOM_PDE_SERVER == type ||
+ LOC_AGPS_MPC_SERVER == type) {
+ struct in_addr addr;
+ if (!resolve_in_addr(hostname, &addr))
+ {
+ LOC_LOGE("loc_eng_set_server, hostname %s cannot be resolved.\n", hostname);
+ ret = -2;
+ } else {
+ unsigned int ip = htonl(addr.s_addr);
+ loc_eng_msg_set_server_ipv4 *msg(new loc_eng_msg_set_server_ipv4(&loc_eng_data,
+ ip,
+ port,
+ type));
+ msg_q_snd((void*)((LocEngContext*)(loc_eng_data.context))->deferred_q,
+ msg, loc_eng_free_msg);
+ }
+ } else {
+ LOC_LOGE("loc_eng_set_server, type %d cannot be resolved.\n", type);
+ }
+
+ EXIT_LOG(%d, ret);
+ return ret;
+}
+
+/*===========================================================================
+FUNCTION loc_eng_set_server_proxy
+
+DESCRIPTION
+ If loc_eng_set_server is called before loc_eng_init, it doesn't work. This
+ proxy buffers server settings and calls loc_eng_set_server when the client is
+ open.
+
+DEPENDENCIES
+ NONE
+
+RETURN VALUE
+ 0
+
+SIDE EFFECTS
+ N/A
+
+===========================================================================*/
+int loc_eng_set_server_proxy(loc_eng_data_s_type &loc_eng_data,
+ LocServerType type,
+ const char* hostname, int port)
+{
+ ENTRY_LOG_CALLFLOW();
+ int ret_val = 0;
+
+ if (NULL != loc_eng_data.context)
+ {
+ ret_val = loc_eng_set_server(loc_eng_data, type, hostname, port);
+ } else {
+ LOC_LOGW("set_server called before init. save the address, type: %d, hostname: %s, port: %d",
+ (int) type, hostname, port);
+ switch (type)
+ {
+ case LOC_AGPS_SUPL_SERVER:
+ strlcpy(loc_eng_data.supl_host_buf, hostname,
+ sizeof(loc_eng_data.supl_host_buf));
+ loc_eng_data.supl_port_buf = port;
+ loc_eng_data.supl_host_set = 1;
+ break;
+ case LOC_AGPS_CDMA_PDE_SERVER:
+ strlcpy(loc_eng_data.c2k_host_buf, hostname,
+ sizeof(loc_eng_data.c2k_host_buf));
+ loc_eng_data.c2k_port_buf = port;
+ loc_eng_data.c2k_host_set = 1;
+ break;
+ default:
+ LOC_LOGE("loc_eng_set_server_proxy, unknown server type = %d", (int) type);
+ }
+ }
+
+ EXIT_LOG(%d, ret_val);
+ return ret_val;
+}
+
+/*===========================================================================
+FUNCTION loc_eng_agps_ril_update_network_availability
+
+DESCRIPTION
+ Sets data call allow vs disallow flag to modem
+ This is the only member of sLocEngAGpsRilInterface implemented.
+
+DEPENDENCIES
+ None
+
+RETURN VALUE
+ 0: success
+
+SIDE EFFECTS
+ N/A
+
+===========================================================================*/
+void loc_eng_agps_ril_update_network_availability(loc_eng_data_s_type &loc_eng_data,
+ int available, const char* apn)
+{
+ ENTRY_LOG_CALLFLOW();
+ INIT_CHECK(loc_eng_data.context, return);
+ if (apn != NULL)
+ {
+ LOC_LOGD("loc_eng_agps_ril_update_network_availability: APN Name = [%s]\n", apn);
+ int apn_len = smaller_of(strlen (apn), MAX_APN_LEN);
+ loc_eng_msg_set_data_enable *msg(new loc_eng_msg_set_data_enable(&loc_eng_data, apn,
+ apn_len, available));
+ msg_q_snd((void*)((LocEngContext*)(loc_eng_data.context))->deferred_q,
+ msg, loc_eng_free_msg);
+ }
+ EXIT_LOG(%s, VOID_RET);
+}
+
+/*===========================================================================
+FUNCTION loc_eng_report_status
+
+DESCRIPTION
+ Reports GPS engine state to Java layer.
+
+DEPENDENCIES
+ N/A
+
+RETURN VALUE
+ N/A
+
+SIDE EFFECTS
+ N/A
+
+===========================================================================*/
+static void loc_eng_report_status (loc_eng_data_s_type &loc_eng_data, GpsStatusValue status)
+{
+ ENTRY_LOG();
+ // Switch from WAIT to MUTE, for "engine on" or "session begin" event
+ if (status == GPS_STATUS_SESSION_BEGIN || status == GPS_STATUS_ENGINE_ON)
+ {
+ if (loc_eng_data.mute_session_state == LOC_MUTE_SESS_WAIT)
+ {
+ LOC_LOGD("loc_eng_report_status: mute_session_state changed from WAIT to IN SESSION");
+ loc_eng_data.mute_session_state = LOC_MUTE_SESS_IN_SESSION;
+ }
+ }
+
+ // Switch off MUTE session
+ if (loc_eng_data.mute_session_state == LOC_MUTE_SESS_IN_SESSION &&
+ (status == GPS_STATUS_SESSION_END || status == GPS_STATUS_ENGINE_OFF))
+ {
+ LOC_LOGD("loc_eng_report_status: mute_session_state changed from IN SESSION to NONE");
+ loc_eng_data.mute_session_state = LOC_MUTE_SESS_NONE;
+ }
+
+ // Session End is not reported during Android navigating state
+ boolean navigating = loc_eng_data.client_handle->isInSession();
+ if (status != GPS_STATUS_NONE &&
+ !(status == GPS_STATUS_SESSION_END && navigating) &&
+ !(status == GPS_STATUS_SESSION_BEGIN && !navigating))
+ {
+ if (loc_eng_data.mute_session_state != LOC_MUTE_SESS_IN_SESSION)
+ {
+ // Inform GpsLocationProvider about mNavigating status
+ loc_inform_gps_status(loc_eng_data, status);
+ }
+ else {
+ LOC_LOGD("loc_eng_report_status: muting the status report.");
+ }
+ }
+
+ // Only keeps ENGINE ON/OFF in engine_status
+ if (status == GPS_STATUS_ENGINE_ON || status == GPS_STATUS_ENGINE_OFF)
+ {
+ loc_eng_data.engine_status = status;
+ }
+
+ // Only keeps SESSION BEGIN/END in fix_session_status
+ if (status == GPS_STATUS_SESSION_BEGIN || status == GPS_STATUS_SESSION_END)
+ {
+ loc_eng_data.fix_session_status = status;
+ }
+ EXIT_LOG(%s, VOID_RET);
+}
+
+/*===========================================================================
+FUNCTION loc_eng_handle_engine_down
+ loc_eng_handle_engine_up
+
+DESCRIPTION
+ Calls this function when it is detected that modem restart is happening.
+ Either we detected the modem is down or received modem up event.
+ This must be called from the deferred thread to avoid race condition.
+
+DEPENDENCIES
+ None
+
+RETURN VALUE
+ None
+
+SIDE EFFECTS
+ N/A
+
+===========================================================================*/
+void loc_eng_handle_engine_down(loc_eng_data_s_type &loc_eng_data)
+{
+ ENTRY_LOG();
+ loc_eng_ni_reset_on_engine_restart(loc_eng_data);
+ loc_eng_report_status(loc_eng_data, GPS_STATUS_ENGINE_OFF);
+ EXIT_LOG(%s, VOID_RET);
+}
+
+void loc_eng_handle_engine_up(loc_eng_data_s_type &loc_eng_data)
+{
+ ENTRY_LOG();
+ loc_eng_reinit(loc_eng_data);
+
+ if (loc_eng_data.agps_status_cb != NULL) {
+ loc_eng_data.agnss_nif->dropAllSubscribers();
+ loc_eng_data.internet_nif->dropAllSubscribers();
+
+ loc_eng_agps_reinit(loc_eng_data);
+ }
+
+ loc_eng_report_status(loc_eng_data, GPS_STATUS_ENGINE_ON);
+
+ // modem is back up. If we crashed in the middle of navigating, we restart.
+ if (loc_eng_data.client_handle->isInSession()) {
+ // This sets the copy in adapter to modem
+ loc_eng_data.client_handle->setPositionMode(NULL);
+ loc_eng_data.client_handle->setInSession(false);
+ loc_eng_start_handler(loc_eng_data);
+ }
+ EXIT_LOG(%s, VOID_RET);
+}
+
+/*===========================================================================
+FUNCTION loc_eng_deferred_action_thread
+
+DESCRIPTION
+ Main routine for the thread to execute loc_eng commands.
+
+DEPENDENCIES
+ None
+
+RETURN VALUE
+ None
+
+SIDE EFFECTS
+ N/A
+
+===========================================================================*/
+static void loc_eng_deferred_action_thread(void* arg)
+{
+ ENTRY_LOG();
+ loc_eng_msg *msg;
+ static int cnt = 0;
+ LocEngContext* context = (LocEngContext*)arg;
+
+ // make sure we do not run in background scheduling group
+ set_sched_policy(gettid(), SP_FOREGROUND);
+
+ while (1)
+ {
+ LOC_LOGD("%s:%d] %d listening ...\n", __func__, __LINE__, cnt++);
+
+ // we are only sending / receiving msg pointers
+ msq_q_err_type result = msg_q_rcv((void*)context->deferred_q, (void **) &msg);
+ if (eMSG_Q_SUCCESS != result) {
+ LOC_LOGE("%s:%d] fail receiving msg: %s\n", __func__, __LINE__,
+ loc_get_msg_q_status(result));
+ return;
+ }
+
+ loc_eng_data_s_type* loc_eng_data_p = (loc_eng_data_s_type*)msg->owner;
+
+ LOC_LOGD("%s:%d] received msg_id = %s context = %p\n",
+ __func__, __LINE__, loc_get_msg_name(msg->msgid), loc_eng_data_p->context);
+
+ // need to ensure the instance data is valid
+ STATE_CHECK(NULL != loc_eng_data_p->context,
+ "instance cleanup happened",
+ delete msg; return);
+
+ switch(msg->msgid) {
+ case LOC_ENG_MSG_QUIT:
+ {
+ LocEngContext* context = (LocEngContext*)loc_eng_data_p->context;
+ pthread_mutex_lock(&(context->lock));
+ pthread_cond_signal(&(context->cond));
+ pthread_mutex_unlock(&(context->lock));
+ EXIT_LOG(%s, "LOC_ENG_MSG_QUIT, signal the main thread and return");
+ }
+ return;
+
+ case LOC_ENG_MSG_REQUEST_NI:
+ {
+ loc_eng_msg_request_ni *niMsg = (loc_eng_msg_request_ni*)msg;
+ loc_eng_ni_request_handler(*loc_eng_data_p, &niMsg->notify, niMsg->passThroughData);
+ }
+ break;
+
+ case LOC_ENG_MSG_INFORM_NI_RESPONSE:
+ {
+ loc_eng_msg_inform_ni_response *nrMsg = (loc_eng_msg_inform_ni_response*)msg;
+ loc_eng_data_p->client_handle->informNiResponse(nrMsg->response,
+ nrMsg->passThroughData);
+ }
+ break;
+
+ case LOC_ENG_MSG_START_FIX:
+ loc_eng_start_handler(*loc_eng_data_p);
+ break;
+
+ case LOC_ENG_MSG_STOP_FIX:
+ if (loc_eng_data_p->agps_request_pending)
+ {
+ loc_eng_data_p->stop_request_pending = true;
+ LOC_LOGD("loc_eng_stop - deferring stop until AGPS data call is finished\n");
+ } else {
+ loc_eng_stop_handler(*loc_eng_data_p);
+ }
+ break;
+
+ case LOC_ENG_MSG_SET_POSITION_MODE:
+ {
+ loc_eng_msg_position_mode *pmMsg = (loc_eng_msg_position_mode*)msg;
+ loc_eng_data_p->client_handle->setPositionMode(&(pmMsg->pMode));
+ }
+ break;
+
+ case LOC_ENG_MSG_SET_TIME:
+ {
+ loc_eng_msg_set_time *tMsg = (loc_eng_msg_set_time*)msg;
+ loc_eng_data_p->client_handle->setTime(tMsg->time, tMsg->timeReference,
+ tMsg->uncertainty);
+ }
+ break;
+
+ case LOC_ENG_MSG_INJECT_LOCATION:
+ {
+ loc_eng_msg_inject_location *ilMsg = (loc_eng_msg_inject_location*) msg;
+ loc_eng_data_p->client_handle->injectPosition(ilMsg->latitude, ilMsg->longitude,
+ ilMsg->accuracy);
+ }
+ break;
+
+ case LOC_ENG_MSG_SET_SERVER_IPV4:
+ {
+ loc_eng_msg_set_server_ipv4 *ssiMsg = (loc_eng_msg_set_server_ipv4*)msg;
+ loc_eng_data_p->client_handle->setServer(ssiMsg->nl_addr,
+ ssiMsg->port,
+ ssiMsg->serverType);
+ }
+ break;
+
+ case LOC_ENG_MSG_SET_SERVER_URL:
+ {
+ loc_eng_msg_set_server_url *ssuMsg = (loc_eng_msg_set_server_url*)msg;
+ loc_eng_data_p->client_handle->setServer(ssuMsg->url, ssuMsg->len);
+ }
+ break;
+
+ case LOC_ENG_MSG_SUPL_VERSION:
+ {
+ loc_eng_msg_suple_version *svMsg = (loc_eng_msg_suple_version*)msg;
+ loc_eng_data_p->client_handle->setSUPLVersion(svMsg->supl_version);
+ }
+ break;
+
+ case LOC_ENG_MSG_LPP_CONFIG:
+ {
+ loc_eng_msg_lpp_config *svMsg = (loc_eng_msg_lpp_config*)msg;
+ loc_eng_data_p->client_handle->setLPPConfig(svMsg->lpp_config);
+ }
+ break;
+
+ case LOC_ENG_MSG_SET_SENSOR_CONTROL_CONFIG:
+ {
+ loc_eng_msg_sensor_control_config *sccMsg = (loc_eng_msg_sensor_control_config*)msg;
+ loc_eng_data_p->client_handle->setSensorControlConfig(sccMsg->sensorsDisabled);
+ }
+ break;
+
+ case LOC_ENG_MSG_SET_SENSOR_PROPERTIES:
+ {
+ loc_eng_msg_sensor_properties *spMsg = (loc_eng_msg_sensor_properties*)msg;
+ loc_eng_data_p->client_handle->setSensorProperties(spMsg->gyroBiasVarianceRandomWalk_valid,
+ spMsg->gyroBiasVarianceRandomWalk,
+ spMsg->accelRandomWalk_valid,
+ spMsg->accelRandomWalk,
+ spMsg->angleRandomWalk_valid,
+ spMsg->angleRandomWalk,
+ spMsg->rateRandomWalk_valid,
+ spMsg->rateRandomWalk,
+ spMsg->velocityRandomWalk_valid,
+ spMsg->velocityRandomWalk);
+ }
+ break;
+
+ case LOC_ENG_MSG_SET_SENSOR_PERF_CONTROL_CONFIG:
+ {
+ loc_eng_msg_sensor_perf_control_config *spccMsg = (loc_eng_msg_sensor_perf_control_config*)msg;
+ loc_eng_data_p->client_handle->setSensorPerfControlConfig(spccMsg->controlMode, spccMsg->accelSamplesPerBatch, spccMsg->accelBatchesPerSec,
+ spccMsg->gyroSamplesPerBatch, spccMsg->gyroBatchesPerSec,
+ spccMsg->accelSamplesPerBatchHigh, spccMsg->accelBatchesPerSecHigh,
+ spccMsg->gyroSamplesPerBatchHigh, spccMsg->gyroBatchesPerSecHigh,
+ spccMsg->algorithmConfig);
+ }
+ break;
+
+ case LOC_ENG_MSG_EXT_POWER_CONFIG:
+ {
+ loc_eng_msg_ext_power_config *pwrMsg = (loc_eng_msg_ext_power_config*)msg;
+ loc_eng_data_p->client_handle->setExtPowerConfig(pwrMsg->isBatteryCharging);
+ }
+ break;
+
+ case LOC_ENG_MSG_REPORT_POSITION:
+ if (loc_eng_data_p->mute_session_state != LOC_MUTE_SESS_IN_SESSION)
+ {
+ bool reported = false;
+ loc_eng_msg_report_position *rpMsg = (loc_eng_msg_report_position*)msg;
+ if (loc_eng_data_p->location_cb != NULL) {
+ if (LOC_SESS_FAILURE == rpMsg->status) {
+ // in case we want to handle the failure case
+ loc_eng_data_p->location_cb(NULL, NULL);
+ reported = true;
+ }
+ // what's in the else if is... (line by line)
+ // 1. this is a good fix; or
+ // 2. (must be intermediate fix... implicit)
+ // 2.1 we accepte intermediate; and
+ // 2.2 it is NOT the case that
+ // 2.2.1 there is inaccuracy; and
+ // 2.2.2 we care about inaccuracy; and
+ // 2.2.3 the inaccuracy exceeds our tolerance
+ else if (LOC_SESS_SUCCESS == rpMsg->status ||
+ (LOC_SESS_INTERMEDIATE == loc_eng_data_p->intermediateFix &&
+ !((rpMsg->location.flags & GPS_LOCATION_HAS_ACCURACY) &&
+ (gps_conf.ACCURACY_THRES != 0) &&
+ (rpMsg->location.accuracy > gps_conf.ACCURACY_THRES)))) {
+ loc_eng_data_p->location_cb((GpsLocation*)&(rpMsg->location),
+ (void*)rpMsg->locationExt);
+ reported = true;
+ }
+ }
+
+ // if we have reported this fix
+ if (reported &&
+ // and if this is a singleshot
+ GPS_POSITION_RECURRENCE_SINGLE ==
+ loc_eng_data_p->client_handle->getPositionMode().recurrence) {
+ if (LOC_SESS_INTERMEDIATE == rpMsg->status) {
+ // modem could be still working for a final fix,
+ // although we no longer need it. So stopFix().
+ loc_eng_data_p->client_handle->stopFix();
+ }
+ // turn off the session flag.
+ loc_eng_data_p->client_handle->setInSession(false);
+ }
+
+ // Free the allocated memory for rawData
+ GpsLocation* gp = (GpsLocation*)&(rpMsg->location);
+ if (gp != NULL && gp->rawData != NULL)
+ {
+ delete (char*)gp->rawData;
+ gp->rawData = NULL;
+ gp->rawDataSize = 0;
+ }
+ }
+
+ break;
+
+ case LOC_ENG_MSG_REPORT_SV:
+ if (loc_eng_data_p->mute_session_state != LOC_MUTE_SESS_IN_SESSION)
+ {
+ loc_eng_msg_report_sv *rsMsg = (loc_eng_msg_report_sv*)msg;
+ if (loc_eng_data_p->sv_status_cb != NULL) {
+ loc_eng_data_p->sv_status_cb((GpsSvStatus*)&(rsMsg->svStatus),
+ (void*)rsMsg->svExt);
+ }
+ }
+ break;
+
+ case LOC_ENG_MSG_REPORT_STATUS:
+ loc_eng_report_status(*loc_eng_data_p, ((loc_eng_msg_report_status*)msg)->status);
+ break;
+
+ case LOC_ENG_MSG_REPORT_NMEA:
+ if (NULL != loc_eng_data_p->nmea_cb) {
+ loc_eng_msg_report_nmea* nmMsg = (loc_eng_msg_report_nmea*)msg;
+ struct timeval tv;
+ gettimeofday(&tv, (struct timezone *) NULL);
+ int64_t now = tv.tv_sec * 1000LL + tv.tv_usec / 1000;
+ CALLBACK_LOG_CALLFLOW("nmea_cb", %p, nmMsg->nmea);
+ loc_eng_data_p->nmea_cb(now, nmMsg->nmea, nmMsg->length);
+ }
+ break;
+
+ case LOC_ENG_MSG_REQUEST_BIT:
+ {
+ AgpsStateMachine* stateMachine;
+ loc_eng_msg_request_bit* brqMsg = (loc_eng_msg_request_bit*)msg;
+ if (brqMsg->ifType == LOC_ENG_IF_REQUEST_TYPE_SUPL) {
+ stateMachine = loc_eng_data_p->agnss_nif;
+ } else if (brqMsg->ifType == LOC_ENG_IF_REQUEST_TYPE_ANY) {
+ stateMachine = loc_eng_data_p->internet_nif;
+ } else {
+ LOC_LOGD("%s]%d: unknown I/F request type = 0x%x\n", __func__, __LINE__, brqMsg->ifType);
+ break;
+ }
+ BITSubscriber subscriber(stateMachine, brqMsg->ipv4Addr, brqMsg->ipv6Addr);
+
+ stateMachine->subscribeRsrc((Subscriber*)&subscriber);
+ }
+ break;
+
+ case LOC_ENG_MSG_RELEASE_BIT:
+ {
+ AgpsStateMachine* stateMachine;
+ loc_eng_msg_release_bit* brlMsg = (loc_eng_msg_release_bit*)msg;
+ if (brlMsg->ifType == LOC_ENG_IF_REQUEST_TYPE_SUPL) {
+ stateMachine = loc_eng_data_p->agnss_nif;
+ } else if (brlMsg->ifType == LOC_ENG_IF_REQUEST_TYPE_ANY) {
+ stateMachine = loc_eng_data_p->internet_nif;
+ } else {
+ LOC_LOGD("%s]%d: unknown I/F request type = 0x%x\n", __func__, __LINE__, brlMsg->ifType);
+ break;
+ }
+ BITSubscriber subscriber(stateMachine, brlMsg->ipv4Addr, brlMsg->ipv6Addr);
+
+ stateMachine->unsubscribeRsrc((Subscriber*)&subscriber);
+ }
+ break;
+
+ case LOC_ENG_MSG_REQUEST_ATL:
+ {
+ loc_eng_msg_request_atl* arqMsg = (loc_eng_msg_request_atl*)msg;
+ boolean backwardCompatibleMode = AGPS_TYPE_INVALID == arqMsg->type;
+ AgpsStateMachine* stateMachine = (AGPS_TYPE_SUPL == arqMsg->type ||
+ backwardCompatibleMode) ?
+ loc_eng_data_p->agnss_nif :
+ loc_eng_data_p->internet_nif;
+ ATLSubscriber subscriber(arqMsg->handle,
+ stateMachine,
+ loc_eng_data_p->client_handle,
+ backwardCompatibleMode);
+
+ stateMachine->subscribeRsrc((Subscriber*)&subscriber);
+ }
+ break;
+
+ case LOC_ENG_MSG_RELEASE_ATL:
+ {
+ loc_eng_msg_release_atl* arlMsg = (loc_eng_msg_release_atl*)msg;
+ ATLSubscriber s1(arlMsg->handle,
+ loc_eng_data_p->agnss_nif,
+ loc_eng_data_p->client_handle,
+ false);
+ // attempt to unsubscribe from agnss_nif first
+ if (! loc_eng_data_p->agnss_nif->unsubscribeRsrc((Subscriber*)&s1)) {
+ ATLSubscriber s2(arlMsg->handle,
+ loc_eng_data_p->internet_nif,
+ loc_eng_data_p->client_handle,
+ false);
+ // if unsuccessful, try internet_nif
+ loc_eng_data_p->internet_nif->unsubscribeRsrc((Subscriber*)&s2);
+ }
+ }
+ break;
+
+ case LOC_ENG_MSG_REQUEST_WIFI:
+ {
+ loc_eng_msg_request_wifi *wrqMsg = (loc_eng_msg_request_wifi *)msg;
+ if (wrqMsg->senderId == LOC_ENG_IF_REQUEST_SENDER_ID_QUIPC ||
+ wrqMsg->senderId == LOC_ENG_IF_REQUEST_SENDER_ID_MSAPM) {
+ AgpsStateMachine* stateMachine = loc_eng_data_p->wifi_nif;
+ WIFISubscriber subscriber(stateMachine, wrqMsg->ssid, wrqMsg->password, wrqMsg->senderId);
+ stateMachine->subscribeRsrc((Subscriber*)&subscriber);
+ } else {
+ LOC_LOGE("%s]%d ERROR: unknown sender ID", __func__, __LINE__);
+ break;
+ }
+ }
+ break;
+
+ case LOC_ENG_MSG_RELEASE_WIFI:
+ {
+ AgpsStateMachine* stateMachine = loc_eng_data_p->wifi_nif;
+ loc_eng_msg_release_wifi* wrlMsg = (loc_eng_msg_release_wifi*)msg;
+ WIFISubscriber subscriber(stateMachine, wrlMsg->ssid, wrlMsg->password, wrlMsg->senderId);
+ stateMachine->unsubscribeRsrc((Subscriber*)&subscriber);
+ }
+ break;
+
+ case LOC_ENG_MSG_REQUEST_XTRA_DATA:
+ if (loc_eng_data_p->xtra_module_data.download_request_cb != NULL)
+ {
+ loc_eng_data_p->xtra_module_data.download_request_cb();
+ }
+ break;
+
+ case LOC_ENG_MSG_REQUEST_TIME:
+ break;
+
+ case LOC_ENG_MSG_REQUEST_POSITION:
+ break;
+
+ case LOC_ENG_MSG_DELETE_AIDING_DATA:
+ loc_eng_data_p->aiding_data_for_deletion |= ((loc_eng_msg_delete_aiding_data*)msg)->type;
+ break;
+
+ case LOC_ENG_MSG_ENABLE_DATA:
+ {
+ loc_eng_msg_set_data_enable *unaMsg = (loc_eng_msg_set_data_enable*)msg;
+ loc_eng_data_p->client_handle->enableData(unaMsg->enable);
+ loc_eng_data_p->client_handle->setAPN(unaMsg->apn, unaMsg->length);
+ }
+ break;
+
+ case LOC_ENG_MSG_INJECT_XTRA_DATA:
+ {
+ loc_eng_msg_inject_xtra_data *xdMsg = (loc_eng_msg_inject_xtra_data*)msg;
+ loc_eng_data_p->client_handle->setXtraData(xdMsg->data, xdMsg->length);
+ }
+ break;
+
+ case LOC_ENG_MSG_ATL_OPEN_SUCCESS:
+ {
+ loc_eng_msg_atl_open_success *aosMsg = (loc_eng_msg_atl_open_success*)msg;
+ AgpsStateMachine* stateMachine;
+ switch (aosMsg->agpsType) {
+ case AGPS_TYPE_WIFI: {
+ stateMachine = loc_eng_data_p->wifi_nif;
+ break;
+ }
+ case AGPS_TYPE_SUPL: {
+ stateMachine = loc_eng_data_p->agnss_nif;
+ break;
+ }
+ default: {
+ stateMachine = loc_eng_data_p->internet_nif;
+ }
+ }
+
+ stateMachine->setBearer(aosMsg->bearerType);
+ stateMachine->setAPN(aosMsg->apn, aosMsg->length);
+ stateMachine->onRsrcEvent(RSRC_GRANTED);
+ }
+ break;
+
+ case LOC_ENG_MSG_ATL_CLOSED:
+ {
+ loc_eng_msg_atl_closed *acsMsg = (loc_eng_msg_atl_closed*)msg;
+ AgpsStateMachine* stateMachine;
+ switch (acsMsg->agpsType) {
+ case AGPS_TYPE_WIFI: {
+ stateMachine = loc_eng_data_p->wifi_nif;
+ break;
+ }
+ case AGPS_TYPE_SUPL: {
+ stateMachine = loc_eng_data_p->agnss_nif;
+ break;
+ }
+ default: {
+ stateMachine = loc_eng_data_p->internet_nif;
+ }
+ }
+
+ stateMachine->onRsrcEvent(RSRC_RELEASED);
+ }
+ break;
+
+ case LOC_ENG_MSG_ATL_OPEN_FAILED:
+ {
+ loc_eng_msg_atl_open_failed *aofMsg = (loc_eng_msg_atl_open_failed*)msg;
+ AgpsStateMachine* stateMachine;
+ switch (aofMsg->agpsType) {
+ case AGPS_TYPE_WIFI: {
+ stateMachine = loc_eng_data_p->wifi_nif;
+ break;
+ }
+ case AGPS_TYPE_SUPL: {
+ stateMachine = loc_eng_data_p->agnss_nif;
+ break;
+ }
+ default: {
+ stateMachine = loc_eng_data_p->internet_nif;
+ }
+ }
+
+ stateMachine->onRsrcEvent(RSRC_DENIED);
+ }
+ break;
+
+ case LOC_ENG_MSG_ENGINE_DOWN:
+ loc_eng_handle_engine_down(*loc_eng_data_p);
+ break;
+
+ case LOC_ENG_MSG_ENGINE_UP:
+ loc_eng_handle_engine_up(*loc_eng_data_p);
+ break;
+
+ case LOC_ENG_MSG_REQUEST_NETWORK_POSIITON:
+ {
+ loc_eng_msg_request_network_position *nlprequestmsg = (loc_eng_msg_request_network_position*)msg;
+ //loc_eng_handle_request_network_position(nlprequestmsg );
+ LOC_LOGD("Received n/w position request from ULP.Request type %d Periodicity: %d\n",
+ nlprequestmsg->networkPosRequest.request_type,
+ nlprequestmsg->networkPosRequest.interval_ms);
+ if(loc_eng_data_p->ulp_network_callback != NULL)
+ {
+ loc_eng_data_p->ulp_network_callback((UlpNetworkRequestPos*)&(nlprequestmsg->networkPosRequest));
+ }
+ else
+ LOC_LOGE("Ulp Network call back not initialized");
+ }
+ break;
+
+ case LOC_ENG_MSG_REQUEST_PHONE_CONTEXT:
+ {
+ loc_eng_msg_request_phone_context *contextReqMsg = (loc_eng_msg_request_phone_context*)msg;
+ LOC_LOGD("Received phone context request from ULP.context_type 0x%x,request_type 0x%x ",
+ contextReqMsg->contextRequest.context_type,contextReqMsg->contextRequest.request_type)
+ if(loc_eng_data_p->ulp_phone_context_req_cb != NULL)
+ {
+ loc_eng_data_p->ulp_phone_context_req_cb((UlpPhoneContextRequest*)&(contextReqMsg->contextRequest));
+ }
+ else
+ LOC_LOGE("Ulp Phone context request call back not initialized");
+ }
+ break;
+
+ case LOC_ENG_MSG_PRIVACY:
+ {
+ loc_eng_msg_privacy *privacyMsg = (loc_eng_msg_privacy*)msg;
+ LOC_LOGE("Ignoring call to setPrivacy");
+ //loc_eng_data_p->client_handle->setPrivacy(privacyMsg->privacy_setting);
+ }
+ break;
+
+ default:
+ LOC_LOGE("unsupported msgid = %d\n", msg->msgid);
+ break;
+ }
+
+ if ( (msg->msgid == LOC_ENG_MSG_ATL_OPEN_FAILED) |
+ (msg->msgid == LOC_ENG_MSG_ATL_CLOSED) |
+ (msg->msgid == LOC_ENG_MSG_ATL_OPEN_SUCCESS) )
+ {
+ loc_eng_data_p->agps_request_pending = false;
+ if (loc_eng_data_p->stop_request_pending) {
+ loc_eng_stop_handler(*loc_eng_data_p);
+ loc_eng_data_p->stop_request_pending = false;
+ }
+ }
+ loc_eng_data_p->stop_request_pending = false;
+
+ if (loc_eng_data_p->engine_status != GPS_STATUS_ENGINE_ON &&
+ loc_eng_data_p->aiding_data_for_deletion != 0)
+ {
+ loc_eng_data_p->client_handle->deleteAidingData(loc_eng_data_p->aiding_data_for_deletion);
+ loc_eng_data_p->aiding_data_for_deletion = 0;
+ }
+
+ delete msg;
+ }
+
+ EXIT_LOG(%s, VOID_RET);
+}
+
+/*===========================================================================
+FUNCTION loc_eng_ulp_init
+
+DESCRIPTION
+ This function dynamically loads the libulp.so and calls
+ its init function to start up the ulp module
+
+DEPENDENCIES
+ None
+
+RETURN VALUE
+ 0: no error
+ -1: errors
+
+SIDE EFFECTS
+ N/A
+
+===========================================================================*/
+int loc_eng_ulp_init(loc_eng_data_s_type &loc_eng_data, const ulpInterface * loc_eng_ulpInf)
+{
+ ENTRY_LOG();
+ int ret_val=-1;
+
+ if(loc_eng_ulpInf != NULL)
+ {
+ // Initialize the ULP interface
+ ((ulpInterface *)loc_eng_ulpInf)->init(loc_eng_data);
+ loc_eng_data.ulp_initialized = TRUE;
+ }
+ ret_val = 0;
+exit:
+ EXIT_LOG(%d, ret_val);
+ return ret_val;
+}
+
+/*===========================================================================
+FUNCTION loc_eng_inject_raw_command
+
+DESCRIPTION
+ This is used to send special test modem commands from the applications
+ down into the HAL
+DEPENDENCIES
+ N/A
+
+RETURN VALUE
+ 0: success
+
+SIDE EFFECTS
+ N/A
+
+===========================================================================*/
+bool loc_eng_inject_raw_command(loc_eng_data_s_type &loc_eng_data,
+ char* command, int length)
+{
+ ENTRY_LOG_CALLFLOW();
+ INIT_CHECK(loc_eng_data.context, return -1);
+ boolean ret_val;
+ LOC_LOGD("loc_eng_send_extra_command: %s\n", command);
+ ret_val = TRUE;
+
+ if((loc_eng_data.ulp_initialized == true) && (gps_conf.CAPABILITIES & ULP_CAPABILITY))
+ {
+ ulp_msg_inject_raw_command *msg(
+ new ulp_msg_inject_raw_command(&loc_eng_data,command, length));
+ msg_q_snd( (void*)((LocEngContext*)(loc_eng_data.context))->ulp_q
+ , msg, loc_eng_free_msg);
+ ret_val = 0;
+ }else
+ {
+ ret_val = -1;
+ }
+
+
+ EXIT_LOG(%s, loc_logger_boolStr[ret_val!=0]);
+ return ret_val;
+}
+/*===========================================================================
+FUNCTION loc_eng_update_criteria
+
+DESCRIPTION
+ This is used to inform the ULP module of new unique criteria that are passed
+ in by the applications
+DEPENDENCIES
+ N/A
+
+RETURN VALUE
+ 0: success
+
+SIDE EFFECTS
+ N/A
+
+===========================================================================*/
+int loc_eng_update_criteria(loc_eng_data_s_type &loc_eng_data,
+ UlpLocationCriteria criteria)
+{
+ ENTRY_LOG_CALLFLOW();
+ INIT_CHECK(loc_eng_data.context, return -1);
+ int ret_val;
+
+ if((loc_eng_data.ulp_initialized == true) && (gps_conf.CAPABILITIES & ULP_CAPABILITY))
+ {
+ LOC_LOGD("SJ:loc_eng_update_criteria: valid 0x%x action:%d, minTime:%ld, minDistance:%f, singleShot:%d, horizontalAccuracy:%d, powerRequirement:%d \n",
+ criteria.valid_mask, criteria.action, criteria.min_interval, criteria.min_distance, criteria.recurrence_type, criteria.preferred_horizontal_accuracy,
+ criteria.preferred_power_consumption );
+ ulp_msg_update_criteria *msg(
+ new ulp_msg_update_criteria(&loc_eng_data,criteria));
+ msg_q_snd( (void*)((LocEngContext*)(loc_eng_data.context))->ulp_q
+ , msg, loc_eng_free_msg);
+ ret_val = 0;
+ }else
+ {
+ ret_val = -1;
+ }
+ EXIT_LOG(%d, ret_val);
+ return ret_val;
+}
+
+/*===========================================================================
+FUNCTION loc_eng_ulp_phone_context_settings_update
+
+DESCRIPTION
+ This is used to inform the ULP module of phone settings changes carried out
+ by the users
+DEPENDENCIES
+ N/A
+
+RETURN VALUE
+ 0: success
+
+SIDE EFFECTS
+ N/A
+
+===========================================================================*/
+
+int loc_eng_ulp_phone_context_settings_update(loc_eng_data_s_type &loc_eng_data,
+ UlpPhoneContextSettings *settings)
+{
+ ENTRY_LOG();
+ int ret_val = -1;
+
+ LOC_LOGD("loc_eng_ulp_phone_context_settings: context_type - 0x%x is_agps_enabled - %d "
+ "is_battery_charging %d ,is_gps_enabled %d, is_network_position_available %d,"
+ "is_wifi_setting_enabled %d, is_agps_setting_enabled %d, is_enh_location_services_enabled %d\n",
+ settings->context_type ,settings->is_agps_enabled,settings->is_battery_charging,
+ settings->is_gps_enabled, settings->is_network_position_available,
+ settings->is_wifi_setting_enabled, settings->is_agps_enabled,
+ settings->is_enh_location_services_enabled );
+
+ if((loc_eng_data.ulp_initialized == true) && (gps_conf.CAPABILITIES & ULP_CAPABILITY))
+ {
+ ulp_msg_inject_phone_context_settings *msg
+ (new ulp_msg_inject_phone_context_settings(&loc_eng_data, *settings));
+ msg_q_snd( (void*)((LocEngContext*)(loc_eng_data.context))->ulp_q, msg, loc_eng_free_msg);
+ ret_val = 0;
+ }
+
+ // Send battery information to modem for processing.
+ if(settings->context_type & ULP_PHONE_CONTEXT_BATTERY_CHARGING_STATE)
+ {
+ loc_eng_msg_ext_power_config *msg(new loc_eng_msg_ext_power_config(&loc_eng_data, settings->is_battery_charging));
+ msg_q_snd( (void*)((LocEngContext*)(loc_eng_data.context))->deferred_q, msg, loc_eng_free_msg);
+ }
+
+ EXIT_LOG(%d, ret_val);
+ return ret_val;
+}
+/*===========================================================================
+FUNCTION loc_eng_ulp_network_init
+
+DESCRIPTION
+ Initialize the ULP network interface.
+
+DEPENDENCIES
+ NONE
+
+RETURN VALUE
+ 0
+
+SIDE EFFECTS
+ N/A
+
+===========================================================================*/
+int loc_eng_ulp_phone_context_init(loc_eng_data_s_type &loc_eng_data,UlpPhoneContextCallbacks *callback)
+{
+ ENTRY_LOG();
+ loc_eng_data.ulp_phone_context_req_cb = callback->ulp_request_phone_context_cb ;
+ int ret_val =0;
+ EXIT_LOG(%d, ret_val);
+ return ret_val;
+}
+
+/*===========================================================================
+FUNCTION loc_eng_ulp_network_init
+
+DESCRIPTION
+ Initialize the ULP network interface.
+
+DEPENDENCIES
+ NONE
+
+RETURN VALUE
+ 0
+
+SIDE EFFECTS
+ N/A
+
+===========================================================================*/
+int loc_eng_ulp_network_init(loc_eng_data_s_type &loc_eng_data,
+ UlpNetworkLocationCallbacks *callbacks)
+{
+ ENTRY_LOG_CALLFLOW();
+ loc_eng_data.ulp_network_callback = callbacks->ulp_network_location_request_cb;
+ int ret_val =0;
+ EXIT_LOG(%d, ret_val);
+ return ret_val;
+}
+
+
+/*===========================================================================
+FUNCTION loc_eng_ulp_send_network_position
+
+DESCRIPTION
+ Ulp send data
+
+DEPENDENCIES
+ NONE
+
+RETURN VALUE
+ 0
+
+SIDE EFFECTS
+ N/A
+
+===========================================================================*/
+int loc_eng_ulp_send_network_position(loc_eng_data_s_type &loc_eng_data,
+ UlpNetworkPositionReport *position_report)
+{
+ ENTRY_LOG();
+ int ret_val = 0;
+ if((loc_eng_data.ulp_initialized == true) && (gps_conf.CAPABILITIES & ULP_CAPABILITY))
+ {
+ ulp_msg_inject_network_position *msg
+ (new ulp_msg_inject_network_position(&loc_eng_data, *position_report));
+ msg_q_snd( (void*)((LocEngContext*)(loc_eng_data.context))->ulp_q
+ , msg, loc_eng_free_msg);
+ ret_val = 0;
+ }else
+ {
+ ret_val = -1;
+ }
+ EXIT_LOG(%d, ret_val);
+ return ret_val;
+}
+/*===========================================================================
+FUNCTION loc_eng_read_config
+
+DESCRIPTION
+ Initiates the reading of the gps config file stored in /etc dir
+
+DEPENDENCIES
+ None
+
+RETURN VALUE
+ 0: success
+
+SIDE EFFECTS
+ N/A
+
+===========================================================================*/
+int loc_eng_read_config(void)
+{
+ ENTRY_LOG_CALLFLOW();
+ if(gpsConfigAlreadyRead == false)
+ {
+ // Initialize our defaults before reading of configuration file overwrites them.
+ loc_default_parameters();
+ // Ee only want to parse the conf file once. This is a good place to ensure that.
+ // In fact one day the conf file should go into context.
+ UTIL_READ_CONF(GPS_CONF_FILE, loc_parameter_table);
+ gpsConfigAlreadyRead = true;
+ } else {
+ LOC_LOGV("GPS Config file has already been read\n");
+ }
+
+ EXIT_LOG(%d, 0);
+ return 0;
+}
+
+/*===========================================================================
+FUNCTION loc_eng_set_privacy
+
+DESCRIPTION
+ Sets the privacy lock setting (1. GPS on, 0. GPS off).
+
+DEPENDENCIES
+ None
+
+RETURN VALUE
+ 0: success
+
+SIDE EFFECTS
+ N/A
+
+===========================================================================*/
+static int loc_eng_set_privacy(loc_eng_data_s_type &loc_eng_data,
+ int8_t privacy_setting)
+{
+ ENTRY_LOG();
+ INIT_CHECK(loc_eng_data.context, return -1);
+ loc_eng_msg_privacy *msg(
+ new loc_eng_msg_privacy(&loc_eng_data, privacy_setting));
+ msg_q_snd((void*)((LocEngContext*)(loc_eng_data.context))->deferred_q,
+ msg, loc_eng_free_msg);
+
+ EXIT_LOG(%d, 0);
+ return 0;
+}