/* Copyright (c) 2011-2020, The Linux Foundation. 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 The Linux Foundatoin, 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_NDEBUG 0
#define LOG_TAG "LocSvc_ApiV02"

#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sstream>
#include <math.h>
#include <dlfcn.h>
#include <algorithm>

#include <LocApiV02.h>
#include <loc_api_v02_log.h>
#include <loc_api_sync_req.h>
#include <loc_api_v02_client.h>
#include <loc_util_log.h>
#include <gps_extended.h>
#include "loc_pla.h"
#include <loc_cfg.h>
#include <LocContext.h>

using namespace std;
using namespace loc_core;

/* Doppler Conversion from M/S to NS/S */
#define MPS_TO_NSPS         (1.0/0.299792458)

/* Default session id ; TBD needs incrementing for each */
#define LOC_API_V02_DEF_SESSION_ID (1)

/* UMTS CP Address key*/
#define LOC_NI_NOTIF_KEY_ADDRESS           "Address"

/* GPS SV Id offset */
#define GPS_SV_ID_OFFSET        (1)

/* GLONASS SV Id offset */
#define GLONASS_SV_ID_OFFSET    (65)

/* SV ID range */
#define SV_ID_RANGE             (32)

#define BDS_SV_ID_OFFSET         (201)

/* BeiDou SV ID RANGE*/
#define BDS_SV_ID_RANGE          QMI_LOC_DELETE_MAX_BDS_SV_INFO_LENGTH_V02

/* GPS week unknown*/
#define C_GPS_WEEK_UNKNOWN      (65535)

/* seconds per week*/
#define WEEK_MSECS              (60*60*24*7*1000LL)
#define DAY_MSECS               (60*60*24*1000LL)
/* Num days elapsed since GLONASS started from GPS start day 1980->1996 */
#define GPS_GLONASS_DAYS_DIFF    5838
/* number of glonass days in a 4-year interval */
#define GLONASS_DAYS_IN_4YEARS   1461
/* glonass and UTC offset: 3 hours */
#define GLONASS_UTC_OFFSET_HOURS 3

/* speed of light */
#define SPEED_OF_LIGHT          299792458.0

#define MAX_SV_CNT_SUPPORTED_IN_ONE_CONSTELLATION 64

/* number of QMI_LOC messages that need to be checked*/
#define NUMBER_OF_MSG_TO_BE_CHECKED        (3)

/* the time, in seconds, to wait for user response for NI  */
#define LOC_NI_NO_RESPONSE_TIME 20

#define LAT_LONG_TO_RADIANS .000005364418
#define GF_RESPONSIVENESS_THRESHOLD_MSEC_HIGH   120000 //2 mins
#define GF_RESPONSIVENESS_THRESHOLD_MSEC_MEDIUM 900000 //15 mins

#define FLP_BATCHING_MINIMUN_INTERVAL           (1000) // in msec
#define FLP_BATCHING_MIN_TRIP_DISTANCE           1 // 1 meter

template struct loc_core::LocApiResponseData<LocApiBatchData>;
template struct loc_core::LocApiResponseData<LocApiGeofenceData>;
template struct loc_core::LocApiResponseData<LocGpsLocation>;

const float CarrierFrequencies[] = {
    0.0,                                // UNKNOWN
    GPS_L1C_CARRIER_FREQUENCY,          // L1C
    SBAS_L1_CA_CARRIER_FREQUENCY,       // SBAS_L1
    GLONASS_G1_CARRIER_FREQUENCY,       // GLONASS_G1
    QZSS_L1CA_CARRIER_FREQUENCY,        // QZSS_L1CA
    BEIDOU_B1_I_CARRIER_FREQUENCY,      // BEIDOU_B1
    GALILEO_E1_C_CARRIER_FREQUENCY,     // GALILEO_E1
    NAVIC_L5_CARRIER_FREQUENCY };       // NAVIC_L5

/* Gaussian 2D scaling table - scale from x% to 68% confidence */
struct conf_scaler_to_68_pair {
    uint8_t confidence;
    float scaler_to_68;
};
/* length of confScalers array */
#define CONF_SCALER_ARRAY_MAX   (3)
const struct conf_scaler_to_68_pair confScalers[CONF_SCALER_ARRAY_MAX] = {
    {39, 1.517}, // 0 - 39 . Index 0
    {50, 1.287}, // 40 - 50. Index 1
    {63, 1.072}, // 51 - 63. Index 2
};

/*fixed timestamp uncertainty 10 milli second */
static int ap_timestamp_uncertainty = 0;

typedef enum {
    RF_LOSS_GPS_CONF        = 0,
    RF_LOSS_GPS_L5_CONF     = 1,
    RF_LOSS_GLO_LEFT_CONF   = 2,
    RF_LOSS_GLO_CENTER_CONF = 3,
    RF_LOSS_GLO_RIGHT_CONF  = 4,
    RF_LOSS_BDS_CONF        = 5,
    RF_LOSS_BDS_B2A_CONF    = 6,
    RF_LOSS_GAL_CONF        = 7,
    RF_LOSS_GAL_E5_CONF     = 8,
    RF_LOSS_NAVIC_CONF      = 9,
    RF_LOSS_MAX_CONF        = 10
} rfLossConf;

static uint32_t rfLossNV[RF_LOSS_MAX_CONF] = { 0 };

static loc_param_s_type gps_conf_param_table[] =
{
    { "AP_TIMESTAMP_UNCERTAINTY",   &ap_timestamp_uncertainty,          NULL, 'n' },
    { "RF_LOSS_GPS",                &rfLossNV[RF_LOSS_GPS_CONF],        NULL, 'n' },
    { "RF_LOSS_GPS_L5",             &rfLossNV[RF_LOSS_GPS_L5_CONF],     NULL, 'n' },
    { "RF_LOSS_GLO_LEFT",           &rfLossNV[RF_LOSS_GLO_LEFT_CONF],   NULL, 'n' },
    { "RF_LOSS_GLO_CENTER",         &rfLossNV[RF_LOSS_GLO_CENTER_CONF], NULL, 'n' },
    { "RF_LOSS_GLO_RIGHT",          &rfLossNV[RF_LOSS_GLO_RIGHT_CONF],  NULL, 'n' },
    { "RF_LOSS_BDS",                &rfLossNV[RF_LOSS_BDS_CONF],        NULL, 'n' },
    { "RF_LOSS_BDS_B2A",            &rfLossNV[RF_LOSS_BDS_B2A_CONF],    NULL, 'n' },
    { "RF_LOSS_GAL",                &rfLossNV[RF_LOSS_GAL_CONF],        NULL, 'n' },
    { "RF_LOSS_GAL_E5",             &rfLossNV[RF_LOSS_GAL_E5_CONF],     NULL, 'n' },
    { "RF_LOSS_NAVIC",              &rfLossNV[RF_LOSS_NAVIC_CONF],      NULL, 'n' },
};

/* static event callbacks that call the LocApiV02 callbacks*/

/* global event callback, call the eventCb function in loc api adapter v02
   instance */
static void globalEventCb(locClientHandleType clientHandle,
                          uint32_t eventId,
                          const locClientEventIndUnionType eventPayload,
                          void*  pClientCookie)
{
    switch (eventId) {
    case QMI_LOC_EVENT_POSITION_REPORT_IND_V02:
    case QMI_LOC_EVENT_UNPROPAGATED_POSITION_REPORT_IND_V02:
    case QMI_LOC_EVENT_NMEA_IND_V02:
    case QMI_LOC_EVENT_GNSS_SV_INFO_IND_V02:
    case QMI_LOC_EVENT_GNSS_MEASUREMENT_REPORT_IND_V02:
    case QMI_LOC_EVENT_SV_POLYNOMIAL_REPORT_IND_V02:
    case QMI_LOC_EVENT_GPS_EPHEMERIS_REPORT_IND_V02:
    case QMI_LOC_EVENT_GLONASS_EPHEMERIS_REPORT_IND_V02:
    case QMI_LOC_EVENT_BDS_EPHEMERIS_REPORT_IND_V02:
    case QMI_LOC_EVENT_GALILEO_EPHEMERIS_REPORT_IND_V02:
    case QMI_LOC_EVENT_QZSS_EPHEMERIS_REPORT_IND_V02:
    case QMI_LOC_LATENCY_INFORMATION_IND_V02:
        MODEM_LOG_CALLFLOW_DEBUG(%s, loc_get_v02_event_name(eventId));
        break;
    default:
        MODEM_LOG_CALLFLOW(%s, loc_get_v02_event_name(eventId));
        break;
    }

    LocApiV02 *locApiV02Instance = (LocApiV02 *)pClientCookie;

    LOC_LOGv ("client = %p, event id = 0x%X, client cookie ptr = %p",
              clientHandle, eventId, pClientCookie);

    // return if null is passed
    if (NULL == locApiV02Instance)
    {
        LOC_LOGe ("NULL object passed : client = %p, event id = 0x%X",
                  clientHandle, eventId);
        return;
    }
    locApiV02Instance->eventCb(clientHandle, eventId, eventPayload);
}

/* global response callback, it calls the sync request process
   indication function to unblock the request that is waiting on this
   response indication*/
static void globalRespCb(locClientHandleType clientHandle,
                         uint32_t respId,
                         const locClientRespIndUnionType respPayload,
                         uint32_t respPayloadSize,
                         void*  pClientCookie)
{
  MODEM_LOG_CALLFLOW(%s, loc_get_v02_event_name(respId));
  LocApiV02 *locApiV02Instance =
        (LocApiV02 *)pClientCookie;

  LOC_LOGV ("%s:%d] client = %p, resp id = %d, client cookie ptr = %p\n",
                  __func__,  __LINE__,  clientHandle, respId, pClientCookie);

  if( NULL == locApiV02Instance)
  {
    LOC_LOGE ("%s:%d] NULL object passed : client = %p, resp id = %d\n",
                  __func__,  __LINE__,  clientHandle, respId);
    return;
  }

  switch(respId)
  {
    case QMI_LOC_GET_AVAILABLE_WWAN_POSITION_IND_V02:
      if (respPayload.pGetAvailWwanPositionInd != NULL) {
          locApiV02Instance->handleWwanZppFixIndication(*respPayload.pGetAvailWwanPositionInd);
      }
      break;
    case QMI_LOC_GET_BEST_AVAILABLE_POSITION_IND_V02:
        if (respPayload.pGetBestAvailablePositionInd != NULL) {
            locApiV02Instance->handleZppBestAvailableFixIndication(
                    *respPayload.pGetBestAvailablePositionInd);
        }
        [[fallthrough]];
       // Call loc_sync_process_ind below also
    default:
      // process the sync call
      // use pDeleteAssistDataInd as a dummy pointer
      loc_sync_process_ind(clientHandle, respId,
          (void *)respPayload.pDeleteAssistDataInd, respPayloadSize);
      break;
  }
}

/* global error callback, it will call the handle service down
   function in the loc api adapter instance. */
static void globalErrorCb (locClientHandleType clientHandle,
                           locClientErrorEnumType errorId,
                           void *pClientCookie)
{
  LocApiV02 *locApiV02Instance =
          (LocApiV02 *)pClientCookie;

  LOC_LOGV ("%s:%d] client = %p, error id = %d\n, client cookie ptr = %p\n",
                  __func__,  __LINE__,  clientHandle, errorId, pClientCookie);
  if( NULL == locApiV02Instance)
  {
    LOC_LOGE ("%s:%d] NULL object passed : client = %p, error id = %d\n",
                  __func__,  __LINE__,  clientHandle, errorId);
    return;
  }
  locApiV02Instance->errorCb(clientHandle, errorId);
}

/* global structure containing the callbacks */
locClientCallbacksType globalCallbacks =
{
    sizeof(locClientCallbacksType),
    globalEventCb,
    globalRespCb,
    globalErrorCb
};

static void getInterSystemTimeBias(const char* interSystem,
                                   Gnss_InterSystemBiasStructType &interSystemBias,
                                   const qmiLocInterSystemBiasStructT_v02* pInterSysBias)
{
    LOC_LOGd("%s] Mask:%d, TimeBias:%f, TimeBiasUnc:%f,\n",
             interSystem, pInterSysBias->validMask, pInterSysBias->timeBias,
             pInterSysBias->timeBiasUnc);

    interSystemBias.validMask    = pInterSysBias->validMask;
    interSystemBias.timeBias     = pInterSysBias->timeBias;
    interSystemBias.timeBiasUnc  = pInterSysBias->timeBiasUnc;
}

/* Constructor for LocApiV02 */
LocApiV02 :: LocApiV02(LOC_API_ADAPTER_EVENT_MASK_T exMask,
                       ContextBase* context):
    LocApiBase(exMask, context),
    clientHandle(LOC_CLIENT_INVALID_HANDLE_VALUE),
    mQmiMask(0), mInSession(false), mPowerMode(GNSS_POWER_MODE_INVALID),
    mEngineOn(false), mMeasurementsStarted(false),
    mMasterRegisterNotSupported(false),
    mCounter(0), mMinInterval(1000),
    mGnssMeasurements(nullptr),
    mBatchSize(0), mDesiredBatchSize(0),
    mTripBatchSize(0), mDesiredTripBatchSize(0),
    mIsFirstFinalFixReported(false),
    mIsFirstStartFixReq(false),
    mHlosQtimer1(0),
    mHlosQtimer2(0),
    mRefFCount(0),
    mMeasElapsedRealTimeCal(600000000),
    mPositionElapsedRealTimeCal(30000000)
{
  // initialize loc_sync_req interface
  loc_sync_req_init();
  mADRdata.clear();

  UTIL_READ_CONF(LOC_PATH_GPS_CONF, gps_conf_param_table);
}

/* Destructor for LocApiV02 */
LocApiV02 :: ~LocApiV02()
{
    close();
}

LocApiBase* getLocApi(LOC_API_ADAPTER_EVENT_MASK_T exMask,
                      ContextBase* context)
{
    return (LocApiBase*)LocApiV02::createLocApiV02(exMask, context);
}

LocApiBase* LocApiV02::createLocApiV02(LOC_API_ADAPTER_EVENT_MASK_T exMask,
                                       ContextBase* context)
{
    LOC_LOGD("%s:%d]: Creating new LocApiV02", __func__, __LINE__);
    return new LocApiV02(exMask, context);
}

/* Initialize a loc api v02 client AND
   check which loc message are supported by modem */
enum loc_api_adapter_err
LocApiV02 :: open(LOC_API_ADAPTER_EVENT_MASK_T mask)
{
  enum loc_api_adapter_err rtv = LOC_API_ADAPTER_ERR_SUCCESS;
  locClientStatusEnumType status = eLOC_CLIENT_SUCCESS;

  LOC_API_ADAPTER_EVENT_MASK_T newMask = mask & ~mExcludedMask;

  LOC_LOGd("%p Enter mMask: 0x%" PRIx64 "  mQmiMask: 0x%" PRIx64 " mExcludedMask: 0x%" PRIx64 "",
           clientHandle, mMask, mQmiMask, mExcludedMask);

  /* If the client is already open close it first */
  if(LOC_CLIENT_INVALID_HANDLE_VALUE == clientHandle)
  {
    LOC_LOGV ("%s:%d]: reference to this = %p passed in \n",
              __func__, __LINE__, this);
    /* initialize the loc api v02 interface, note that
       the locClientOpen() function will block if the
       service is unavailable for a fixed time out */

    // it is important to cap the mask here, because not all LocApi's
    // can enable the same bits, e.g. foreground and bckground.
    status = locClientOpen(0, &globalCallbacks, &clientHandle, (void *)this);
    if (eLOC_CLIENT_SUCCESS != status ||
        clientHandle == LOC_CLIENT_INVALID_HANDLE_VALUE )
    {
      mMask = 0;
      mNmeaMask = 0;
      mQmiMask = 0;
      LOC_LOGE ("%s:%d]: locClientOpen failed, status = %s\n", __func__,
                __LINE__, loc_get_v02_client_status_name(status));
      rtv = LOC_API_ADAPTER_ERR_FAILURE;
    } else {
        uint64_t supportedMsgList = 0;
        bool gnssMeasurementSupported = false;
        const uint32_t msgArray[NUMBER_OF_MSG_TO_BE_CHECKED] =
        {
            // For - LOC_API_ADAPTER_MESSAGE_LOCATION_BATCHING
            QMI_LOC_GET_BATCH_SIZE_REQ_V02,

            // For - LOC_API_ADAPTER_MESSAGE_BATCHED_GENFENCE_BREACH
            QMI_LOC_EVENT_GEOFENCE_BATCHED_BREACH_NOTIFICATION_IND_V02,

            // For - LOC_API_ADAPTER_MESSAGE_DISTANCE_BASE_TRACKING
            QMI_LOC_START_DBT_REQ_V02
        };

        if (isMaster()) {
            registerMasterClient();
            gnssMeasurementSupported = cacheGnssMeasurementSupport();
            LocContext::injectFeatureConfig(mContext);
        }

        // check the modem
        status = locClientSupportMsgCheck(clientHandle,
                                          msgArray,
                                          NUMBER_OF_MSG_TO_BE_CHECKED,
                                          &supportedMsgList);
        if (eLOC_CLIENT_SUCCESS != status) {
            LOC_LOGE("%s:%d]: Failed to checking QMI_LOC message supported. \n",
                     __func__, __LINE__);
        }

        /** if batching is supported , check if the adaptive batching or
            distance-based batching is supported. */
        uint32_t messageChecker = 1 << LOC_API_ADAPTER_MESSAGE_LOCATION_BATCHING;
        if ((messageChecker & supportedMsgList) == messageChecker) {
            locClientReqUnionType req_union;
            locClientStatusEnumType status = eLOC_CLIENT_SUCCESS;
            qmiLocQueryAonConfigReqMsgT_v02 queryAonConfigReq;
            qmiLocQueryAonConfigIndMsgT_v02 queryAonConfigInd;

            memset(&queryAonConfigReq, 0, sizeof(queryAonConfigReq));
            memset(&queryAonConfigInd, 0, sizeof(queryAonConfigInd));
            queryAonConfigReq.transactionId = LOC_API_V02_DEF_SESSION_ID;

            req_union.pQueryAonConfigReq = &queryAonConfigReq;
            status = locSyncSendReq(QMI_LOC_QUERY_AON_CONFIG_REQ_V02,
                                    req_union,
                                    LOC_ENGINE_SYNC_REQUEST_TIMEOUT,
                                    QMI_LOC_QUERY_AON_CONFIG_IND_V02,
                                    &queryAonConfigInd);

            if (status == eLOC_CLIENT_FAILURE_UNSUPPORTED) {
                LOC_LOGE("%s:%d]: Query AON config is not supported.\n", __func__, __LINE__);
            } else {
                if (status != eLOC_CLIENT_SUCCESS ||
                    queryAonConfigInd.status != eQMI_LOC_SUCCESS_V02) {
                    LOC_LOGE("%s:%d]: Query AON config failed."
                             " status: %s, ind status:%s\n",
                             __func__, __LINE__,
                             loc_get_v02_client_status_name(status),
                             loc_get_v02_qmi_status_name(queryAonConfigInd.status));
                } else {
                    LOC_LOGD("%s:%d]: Query AON config succeeded. aonCapability is %d.\n",
                             __func__, __LINE__, queryAonConfigInd.aonCapability);
                    if (queryAonConfigInd.aonCapability_valid) {
                        if (queryAonConfigInd.aonCapability |
                            QMI_LOC_MASK_AON_TIME_BASED_BATCHING_SUPPORTED_V02) {
                            LOC_LOGD("%s:%d]: LB 1.0 is supported.\n", __func__, __LINE__);
                        }
                        if (queryAonConfigInd.aonCapability |
                            QMI_LOC_MASK_AON_AUTO_BATCHING_SUPPORTED_V02) {
                            LOC_LOGD("%s:%d]: LB 1.5 is supported.\n", __func__, __LINE__);
                            supportedMsgList |=
                                (1 << LOC_API_ADAPTER_MESSAGE_ADAPTIVE_LOCATION_BATCHING);
                        }
                        if (queryAonConfigInd.aonCapability |
                            QMI_LOC_MASK_AON_DISTANCE_BASED_BATCHING_SUPPORTED_V02) {
                            LOC_LOGD("%s:%d]: LB 2.0 is supported.\n", __func__, __LINE__);
                            supportedMsgList |=
                                (1 << LOC_API_ADAPTER_MESSAGE_DISTANCE_BASE_LOCATION_BATCHING);
                        }
                        if (queryAonConfigInd.aonCapability |
                            QMI_LOC_MASK_AON_DISTANCE_BASED_TRACKING_SUPPORTED_V02) {
                            LOC_LOGD("%s:%d]: DBT 2.0 is supported.\n", __func__, __LINE__);
                        }
                        if (queryAonConfigInd.aonCapability |
                            QMI_LOC_MASK_AON_UPDATE_TBF_SUPPORTED_V02) {
                            LOC_LOGD("%s:%d]: Updating tracking TBF on the fly is supported.\n",
                                     __func__, __LINE__);
                            supportedMsgList |=
                                (1 << LOC_API_ADAPTER_MESSAGE_UPDATE_TBF_ON_THE_FLY);
                        }
                        if (queryAonConfigInd.aonCapability |
                            QMI_LOC_MASK_AON_OUTDOOR_TRIP_BATCHING_SUPPORTED_V02) {
                            LOC_LOGD("%s:%d]: OTB is supported.\n",
                                     __func__, __LINE__);
                            supportedMsgList |=
                                (1 << LOC_API_ADAPTER_MESSAGE_OUTDOOR_TRIP_BATCHING);
                        }
                    } else {
                        LOC_LOGE("%s:%d]: AON capability is invalid.\n", __func__, __LINE__);
                    }
                }
            }
        }
        LOC_LOGV("%s:%d]: supportedMsgList is %" PRIu64 ". \n",
                 __func__, __LINE__, supportedMsgList);

        // Query for supported feature list
        locClientReqUnionType req_union;
        locClientStatusEnumType status = eLOC_CLIENT_SUCCESS;
        qmiLocGetSupportedFeatureReqMsgT_v02 getSupportedFeatureList_req;
        qmiLocGetSupportedFeatureIndMsgT_v02 getSupportedFeatureList_ind;

        memset(&getSupportedFeatureList_req, 0, sizeof(getSupportedFeatureList_req));
        memset(&getSupportedFeatureList_ind, 0, sizeof(getSupportedFeatureList_ind));

        req_union.pGetSupportedFeatureReq = &getSupportedFeatureList_req;
        status = locSyncSendReq(QMI_LOC_GET_SUPPORTED_FEATURE_REQ_V02,
                                req_union,
                                LOC_ENGINE_SYNC_REQUEST_TIMEOUT,
                                QMI_LOC_GET_SUPPORTED_FEATURE_IND_V02,
                                &getSupportedFeatureList_ind);
        if (eLOC_CLIENT_SUCCESS != status) {
            LOC_LOGE("%s:%d:%d]: Failed to get features supported from "
                     "QMI_LOC_GET_SUPPORTED_FEATURE_REQ_V02. \n", __func__, __LINE__, status);
        } else {
            LOC_LOGD("%s:%d:%d]: Got list of features supported of length:%d ",
                     __func__, __LINE__, status, getSupportedFeatureList_ind.feature_len);
            for (uint32_t i = 0; i < getSupportedFeatureList_ind.feature_len; i++) {
                LOC_LOGD("Bit-mask of supported features at index:%d is %d",i,
                         getSupportedFeatureList_ind.feature[i]);
            }
        }

        // cache the mpss engine capabilities
       mContext->setEngineCapabilities(supportedMsgList,
            (getSupportedFeatureList_ind.feature_len != 0 ? getSupportedFeatureList_ind.feature:
            NULL), gnssMeasurementSupported);
    }
  }

  if ((eLOC_CLIENT_SUCCESS == status) && (LOC_CLIENT_INVALID_HANDLE_VALUE != clientHandle)) {
    registerEventMask(newMask);
  }

  LOC_LOGd("clientHandle = %p Exit mMask: 0x%" PRIx64 " mQmiMask: 0x%" PRIx64 "",
           clientHandle, mMask, mQmiMask);

  return rtv;
}

void LocApiV02 :: registerEventMask(LOC_API_ADAPTER_EVENT_MASK_T adapterMask)
{
  locClientEventMaskType qmiMask = adjustMaskIfNoSessionOrEngineOff(convertMask(adapterMask));

  LOC_LOGd("clientHandle = %p; mMask: 0x%" PRIx64 "; newMask: 0x%" PRIx64 "; mQmiMask: 0x%" PRIx64
           "; qmiMask: 0x%" PRIx64 "", clientHandle, mMask, adapterMask, mQmiMask, qmiMask);

  if ((qmiMask != mQmiMask) &&
      (locClientRegisterEventMask(clientHandle, qmiMask, isMaster()))) {
    locClientEventMaskType maskDiff = qmiMask ^ mQmiMask;
    if (maskDiff & qmiMask & QMI_LOC_EVENT_MASK_WIFI_REQ_V02) {
      wifiStatusInformSync();
    }

    if (isMaster()) {
      /* Set the SV Measurement Constellation when Measurement Report or Polynomial report is set */
      /* Check if either measurement report or sv polynomial report bit is different in the new
         mask compared to the old mask. If yes then turn that report on or off as requested */
      /* Later change: we need to set the SV Measurement Constellation whenever measurements
         are supported, and that is because other clients (e.g. CHRE need to have measurements
         enabled and those clients cannot set the SV Measurement Constellation since they are
         not master */
      locClientEventMaskType measOrSvPoly = QMI_LOC_EVENT_MASK_GNSS_SV_POLYNOMIAL_REPORT_V02;
      LOC_LOGd("clientHandle: %p isMaster: %d measOrSvPoly: 0x%" PRIx64 " maskDiff: 0x%" PRIx64 "",
               clientHandle, isMaster(), measOrSvPoly, maskDiff);
      if (((maskDiff & measOrSvPoly) != 0)) {
        if (mContext->gnssConstellationConfig()) {
          setSvMeasurementConstellation(qmiMask | QMI_LOC_EVENT_MASK_GNSS_MEASUREMENT_REPORT_V02);
        } else {
          setSvMeasurementConstellation(qmiMask & ~QMI_LOC_EVENT_MASK_GNSS_MEASUREMENT_REPORT_V02);
        }
      }
    }
    mQmiMask = qmiMask;
  }
  mMask = adapterMask;
}

bool LocApiV02::sendRequestForAidingData(locClientEventMaskType qmiMask) {

    qmiLocSetGNSSConstRepConfigReqMsgT_v02 aidingDataReq;
    qmiLocSetGNSSConstRepConfigIndMsgT_v02 aidingDataReqInd;
    locClientStatusEnumType status;
    locClientReqUnionType req_union;

    LOC_LOGd("qmiMask = 0x%" PRIx64 "\n", qmiMask);

    memset(&aidingDataReq, 0, sizeof(aidingDataReq));

    if (qmiMask & QMI_LOC_EVENT_MASK_GNSS_SV_POLYNOMIAL_REPORT_V02) {
        aidingDataReq.reportFullSvPolyDb_valid = true;
        aidingDataReq.reportFullSvPolyDb = true;
    }

    if (qmiMask & QMI_LOC_EVENT_MASK_EPHEMERIS_REPORT_V02) {
        aidingDataReq.reportFullEphemerisDb_valid = true;
        aidingDataReq.reportFullEphemerisDb = true;
    }

    /* Note: Requesting for full KlobucharIonoModel report is based on
       QMI_LOC_EVENT_MASK_GNSS_EVENT_REPORT_V02 bit as there is no separate QMI subscription bit for
       iono model.*/
    if (qmiMask & QMI_LOC_EVENT_MASK_GNSS_EVENT_REPORT_V02) {
        aidingDataReq.reportFullIonoDb_valid = true;
        aidingDataReq.reportFullIonoDb = true;
    }

    req_union.pSetGNSSConstRepConfigReq = &aidingDataReq;
    memset(&aidingDataReqInd, 0, sizeof(aidingDataReqInd));

    status = locSyncSendReq(QMI_LOC_SET_GNSS_CONSTELL_REPORT_CONFIG_V02,
        req_union,
        LOC_ENGINE_SYNC_REQUEST_TIMEOUT,
        QMI_LOC_SET_GNSS_CONSTELL_REPORT_CONFIG_IND_V02,
        &aidingDataReqInd);

    if (status != eLOC_CLIENT_SUCCESS ||
        (aidingDataReqInd.status != eQMI_LOC_SUCCESS_V02 &&
            aidingDataReqInd.status != eQMI_LOC_ENGINE_BUSY_V02)) {
        LOC_LOGe("Request for aiding data failed status: %s, ind status:%s",
            loc_get_v02_client_status_name(status),
            loc_get_v02_qmi_status_name(aidingDataReqInd.status));
    }
    else {
        LOC_LOGd("Request for aiding data succeeded");
    }

    return true;

}

locClientEventMaskType LocApiV02 :: adjustMaskIfNoSessionOrEngineOff(locClientEventMaskType qmiMask)
{
    locClientEventMaskType oldQmiMask = qmiMask;
    if (!mInSession) {
        locClientEventMaskType clearMask = QMI_LOC_EVENT_MASK_POSITION_REPORT_V02 |
                                           QMI_LOC_EVENT_MASK_UNPROPAGATED_POSITION_REPORT_V02 |
                                           QMI_LOC_EVENT_MASK_GNSS_SV_INFO_V02 |
                                           QMI_LOC_EVENT_MASK_NMEA_V02 |
                                           QMI_LOC_EVENT_MASK_ENGINE_STATE_V02 |
                                           QMI_LOC_EVENT_MASK_GNSS_MEASUREMENT_REPORT_V02 |
                                           QMI_LOC_EVENT_MASK_GNSS_NHZ_MEASUREMENT_REPORT_V02 |
                                           QMI_LOC_EVENT_MASK_GNSS_SV_POLYNOMIAL_REPORT_V02 |
                                           QMI_LOC_EVENT_MASK_EPHEMERIS_REPORT_V02 |
                                           QMI_LOC_EVENT_MASK_GNSS_EVENT_REPORT_V02 |
                                           QMI_LOC_EVENT_MASK_NEXT_LS_INFO_REPORT_V02 |
                                           QMI_LOC_EVENT_MASK_LATENCY_INFORMATION_REPORT_V02;
        qmiMask = qmiMask & ~clearMask;
    } else if (!mEngineOn) {
        locClientEventMaskType clearMask = QMI_LOC_EVENT_MASK_NMEA_V02;
        qmiMask = qmiMask & ~clearMask;
    }
    LOC_LOGd("oldQmiMask=%" PRIx64 " qmiMask=%" PRIx64 " mInSession: %d mEngineOn: %d",
            oldQmiMask, qmiMask, mInSession, mEngineOn);
    return qmiMask;
}

enum loc_api_adapter_err LocApiV02 :: close()
{
  enum loc_api_adapter_err rtv =
      // success if either client is already invalid, or
      // we successfully close the handle
      (LOC_CLIENT_INVALID_HANDLE_VALUE == clientHandle ||
       eLOC_CLIENT_SUCCESS == locClientClose(&clientHandle)) ?
      LOC_API_ADAPTER_ERR_SUCCESS : LOC_API_ADAPTER_ERR_FAILURE;

  mMask = 0;
  mQmiMask = 0;
  mInSession = false;
  clientHandle = LOC_CLIENT_INVALID_HANDLE_VALUE;

  return rtv;
}


/* start positioning session */
void LocApiV02 :: startFix(const LocPosMode& fixCriteria, LocApiResponse *adapterResponse)
{
  sendMsg(new LocApiMsg([this, fixCriteria, adapterResponse] () {

  locClientStatusEnumType status;
  locClientReqUnionType req_union;

  qmiLocStartReqMsgT_v02 start_msg;

  qmiLocSetOperationModeReqMsgT_v02 set_mode_msg;
  qmiLocSetOperationModeIndMsgT_v02 set_mode_ind;

    // clear all fields, validity masks
  memset (&start_msg, 0, sizeof(start_msg));
  memset (&set_mode_msg, 0, sizeof(set_mode_msg));
  memset (&set_mode_ind, 0, sizeof(set_mode_ind));

  LOC_LOGV("%s:%d]: start \n", __func__, __LINE__);
  // BOOT KPI marker, print only once for a session
  if (false == mInSession) {
      loc_boot_kpi_marker("L - LocApiV02 startFix, tbf %d", fixCriteria.min_interval);
  }
  fixCriteria.logv();

  mInSession = true;
  mMeasurementsStarted = true;
  registerEventMask(mMask);

  // fill in the start request
  switch(fixCriteria.mode)
  {
    case LOC_POSITION_MODE_MS_BASED:
      set_mode_msg.operationMode = eQMI_LOC_OPER_MODE_MSB_V02;
      break;

    case LOC_POSITION_MODE_MS_ASSISTED:
      set_mode_msg.operationMode = eQMI_LOC_OPER_MODE_MSA_V02;
      break;

    case LOC_POSITION_MODE_RESERVED_4:
      set_mode_msg.operationMode = eQMI_LOC_OPER_MODE_CELL_ID_V02;
        break;

    case LOC_POSITION_MODE_RESERVED_5:
      set_mode_msg.operationMode = eQMI_LOC_OPER_MODE_WWAN_V02;
        break;

    default:
      set_mode_msg.operationMode = eQMI_LOC_OPER_MODE_STANDALONE_V02;
      break;
  }

  req_union.pSetOperationModeReq = &set_mode_msg;

  // send the mode first, before the start message.
  status = locSyncSendReq(QMI_LOC_SET_OPERATION_MODE_REQ_V02,
                          req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT,
                          QMI_LOC_SET_OPERATION_MODE_IND_V02,
                          &set_mode_ind); // NULL?
   //When locSyncSendReq status is time out, more likely the response was lost.
   //startFix will continue as though it is succeeded.
  if ((status != eLOC_CLIENT_SUCCESS && status != eLOC_CLIENT_FAILURE_TIMEOUT) ||
       eQMI_LOC_SUCCESS_V02 != set_mode_ind.status)
  {
    LOC_LOGE ("%s:%d]: set opertion mode failed status = %s, "
                   "ind..status = %s\n", __func__, __LINE__,
              loc_get_v02_client_status_name(status),
              loc_get_v02_qmi_status_name(set_mode_ind.status));
  } else {
      if (status == eLOC_CLIENT_FAILURE_TIMEOUT)
      {
          LOC_LOGE ("%s:%d]: set operation mode timed out\n", __func__, __LINE__);
      }
      start_msg.minInterval_valid = 1;
      start_msg.minInterval = fixCriteria.min_interval;
      mMinInterval = start_msg.minInterval;

      start_msg.horizontalAccuracyLevel_valid = 1;

      if (fixCriteria.preferred_accuracy <= 100)
      {
          // fix needs high accuracy
          start_msg.horizontalAccuracyLevel =  eQMI_LOC_ACCURACY_HIGH_V02;
      }
      else if (fixCriteria.preferred_accuracy <= 1000)
      {
          //fix needs med accuracy
          start_msg.horizontalAccuracyLevel =  eQMI_LOC_ACCURACY_MED_V02;
      }
      else
      {
          //fix needs low accuracy
          start_msg.horizontalAccuracyLevel =  eQMI_LOC_ACCURACY_LOW_V02;
          // limit the scanning max time to 1 min and TBF to 10 min
          // this is to control the power cost for gps for LOW accuracy
          start_msg.positionReportTimeout_valid = 1;
          start_msg.positionReportTimeout = 60000;
          if (start_msg.minInterval < 600000) {
              start_msg.minInterval = 600000;
          }
      }

      start_msg.fixRecurrence_valid = 1;
      if(LOC_GPS_POSITION_RECURRENCE_SINGLE == fixCriteria.recurrence)
      {
          start_msg.fixRecurrence = eQMI_LOC_RECURRENCE_SINGLE_V02;
      }
      else
      {
          start_msg.fixRecurrence = eQMI_LOC_RECURRENCE_PERIODIC_V02;
      }

      //dummy session id
      // TBD: store session ID, check for session id in pos reports.
      start_msg.sessionId = LOC_API_V02_DEF_SESSION_ID;

      //Set whether position report can be shared with other LOC clients
      start_msg.sharePosition_valid = 1;
      start_msg.sharePosition = fixCriteria.share_position;

      if (fixCriteria.credentials[0] != 0) {
          int size1 = sizeof(start_msg.applicationId.applicationName);
          int size2 = sizeof(fixCriteria.credentials);
          int len = ((size1 < size2) ? size1 : size2) - 1;
          memcpy(start_msg.applicationId.applicationName,
                 fixCriteria.credentials,
                 len);

          size1 = sizeof(start_msg.applicationId.applicationProvider);
          size2 = sizeof(fixCriteria.provider);
          len = ((size1 < size2) ? size1 : size2) - 1;
          memcpy(start_msg.applicationId.applicationProvider,
                 fixCriteria.provider,
                 len);

          start_msg.applicationId_valid = 1;
      }

      // config Altitude Assumed
      start_msg.configAltitudeAssumed_valid = 1;
      start_msg.configAltitudeAssumed = eQMI_LOC_ALTITUDE_ASSUMED_IN_GNSS_SV_INFO_DISABLED_V02;

      // set power mode details
      mPowerMode = fixCriteria.powerMode;
      if (GNSS_POWER_MODE_INVALID != fixCriteria.powerMode) {
          start_msg.powerMode_valid = 1;
          start_msg.powerMode.powerMode = convertPowerMode(fixCriteria.powerMode);
          start_msg.powerMode.timeBetweenMeasurement =
                  fixCriteria.timeBetweenMeasurements;
          // Force low accuracy for background power modes
          if (GNSS_POWER_MODE_M3 == fixCriteria.powerMode ||
                  GNSS_POWER_MODE_M4 == fixCriteria.powerMode ||
                  GNSS_POWER_MODE_M5 == fixCriteria.powerMode) {
              start_msg.horizontalAccuracyLevel =  eQMI_LOC_ACCURACY_LOW_V02;
          }
          // Force TBM = TBF for power mode M4
          if (GNSS_POWER_MODE_M4 == fixCriteria.powerMode) {
              start_msg.powerMode.timeBetweenMeasurement = start_msg.minInterval;
          }
      }

      req_union.pStartReq = &start_msg;

      status = locClientSendReq(QMI_LOC_START_REQ_V02, req_union);
  }

  LocationError err = LOCATION_ERROR_GENERAL_FAILURE;
  if (eLOC_CLIENT_SUCCESS == status) {
      err = LOCATION_ERROR_SUCCESS;
  }

  if (adapterResponse != NULL) {
      adapterResponse->returnToSender(err);
  }
  }));

}

/* stop a positioning session */
void LocApiV02 :: stopFix(LocApiResponse *adapterResponse)
{
  sendMsg(new LocApiMsg([this, adapterResponse] () {

  locClientStatusEnumType status;
  locClientReqUnionType req_union;

  qmiLocStopReqMsgT_v02 stop_msg;

  LOC_LOGD(" %s:%d]: stop called \n", __func__, __LINE__);
  loc_boot_kpi_marker("L - LocApiV02 stop Fix session");

  memset(&stop_msg, 0, sizeof(stop_msg));

  // dummy session id
  stop_msg.sessionId = LOC_API_V02_DEF_SESSION_ID;

  req_union.pStopReq = &stop_msg;

  status = locClientSendReq(QMI_LOC_STOP_REQ_V02, req_union);

  mIsFirstFinalFixReported = false;
  mInSession = false;
  mPowerMode = GNSS_POWER_MODE_INVALID;

  // if engine on never happend, deregister events
  // without waiting for Engine Off
  if (!mEngineOn) {
      registerEventMask(mMask);
  }

  // free the memory used to assemble SV measurement from
  // different constellations and bands
  if (!mGnssMeasurements) {
      free(mGnssMeasurements);
      mGnssMeasurements = nullptr;
  }

  if( eLOC_CLIENT_SUCCESS != status)
  {
      LOC_LOGE("%s:%d]: error = %s\n",__func__, __LINE__,
               loc_get_v02_client_status_name(status));
  }

  LocationError err = LOCATION_ERROR_GENERAL_FAILURE;
  if (eLOC_CLIENT_SUCCESS == status) {
      err = LOCATION_ERROR_SUCCESS;
  }

  if (adapterResponse != NULL) {
      adapterResponse->returnToSender(err);
  }
  }));
}

/* inject time into the position engine */
void LocApiV02 ::
    setTime(LocGpsUtcTime time, int64_t timeReference, int uncertainty)
{
  sendMsg(new LocApiMsg([this, time, timeReference, uncertainty] () {

  locClientReqUnionType req_union;
  locClientStatusEnumType status;
  qmiLocInjectUtcTimeReqMsgT_v02  inject_time_msg;
  qmiLocInjectUtcTimeIndMsgT_v02 inject_time_ind;

  memset(&inject_time_msg, 0, sizeof(inject_time_msg));

  inject_time_ind.status = eQMI_LOC_GENERAL_FAILURE_V02;

  inject_time_msg.timeUtc = time;

  inject_time_msg.timeUtc += (int64_t)(elapsedRealtime() - timeReference);

  inject_time_msg.timeUnc = uncertainty;

  req_union.pInjectUtcTimeReq = &inject_time_msg;

  LOC_LOGV ("%s:%d]: uncertainty = %d\n", __func__, __LINE__,
                 uncertainty);

  status = locSyncSendReq(QMI_LOC_INJECT_UTC_TIME_REQ_V02,
                          req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT,
                          QMI_LOC_INJECT_UTC_TIME_IND_V02,
                          &inject_time_ind);

  if (status != eLOC_CLIENT_SUCCESS ||
      eQMI_LOC_SUCCESS_V02 != inject_time_ind.status)
  {
    LOC_LOGE ("%s:%d] status = %s, ind..status = %s\n", __func__,  __LINE__,
              loc_get_v02_client_status_name(status),
              loc_get_v02_qmi_status_name(inject_time_ind.status));
  }

  }));
}

/* inject position into the position engine */
void LocApiV02 ::
    injectPosition(double latitude, double longitude, float accuracy, bool onDemandCpi)
{
    Location location = {};

    location.flags |= LOCATION_HAS_LAT_LONG_BIT;
    location.latitude = latitude;
    location.longitude = longitude;

    location.flags |= LOCATION_HAS_ACCURACY_BIT;
    location.accuracy = accuracy;

    struct timespec time_info_current;
    if(clock_gettime(CLOCK_REALTIME,&time_info_current) == 0) //success
    {
        location.timestamp = (time_info_current.tv_sec)*1e3 +
            (time_info_current.tv_nsec)/1e6;
    }

    injectPosition(location, onDemandCpi);
}

void LocApiV02::injectPosition(const Location& location, bool onDemandCpi)
{
    sendMsg(new LocApiMsg([this, location, onDemandCpi] () {

    qmiLocInjectPositionReqMsgT_v02 injectPositionReq;
    memset(&injectPositionReq, 0, sizeof(injectPositionReq));

    if (location.timestamp > 0) {
        injectPositionReq.timestampUtc_valid = 1;
        injectPositionReq.timestampUtc = location.timestamp;
    }

    if (LOCATION_HAS_LAT_LONG_BIT & location.flags) {
        injectPositionReq.latitude_valid = 1;
        injectPositionReq.longitude_valid = 1;
        injectPositionReq.latitude = location.latitude;
        injectPositionReq.longitude = location.longitude;
    }

    if (LOCATION_HAS_ACCURACY_BIT & location.flags) {
        injectPositionReq.horUncCircular_valid = 1;
        injectPositionReq.horUncCircular = location.accuracy;
        injectPositionReq.horConfidence_valid = 1;
        injectPositionReq.horConfidence = 68;
        injectPositionReq.rawHorUncCircular_valid = 1;
        injectPositionReq.rawHorUncCircular = location.accuracy;
        injectPositionReq.rawHorConfidence_valid = 1;
        injectPositionReq.rawHorConfidence = 68;

        // We don't wish to advertise accuracy better than 1000 meters to Modem
        if (injectPositionReq.horUncCircular < 1000) {
            injectPositionReq.horUncCircular = 1000;
        }
    }

    if (LOCATION_HAS_ALTITUDE_BIT & location.flags) {
        injectPositionReq.altitudeWrtEllipsoid_valid = 1;
        injectPositionReq.altitudeWrtEllipsoid = location.altitude;
        injectPositionReq.altSourceInfo_valid = 1;
        injectPositionReq.altSourceInfo.source = eQMI_LOC_ALT_SRC_OTHER_V02;
        injectPositionReq.altSourceInfo.linkage = eQMI_LOC_ALT_SRC_LINKAGE_FULLY_INTERDEPENDENT_V02;
    }

    if (LOCATION_HAS_VERTICAL_ACCURACY_BIT & location.flags) {
        injectPositionReq.vertUnc_valid = 1;
        injectPositionReq.vertUnc = location.verticalAccuracy;
        injectPositionReq.vertConfidence_valid = 1;
        injectPositionReq.vertConfidence = 68;
    }

    injectPositionReq.positionSrc_valid = 1;
    injectPositionReq.positionSrc = eQMI_LOC_POSITION_SRC_OTHER_V02;

    if (onDemandCpi) {
        injectPositionReq.onDemandCpi_valid = 1;
        injectPositionReq.onDemandCpi = 1;
    }

    LOC_LOGv("Lat=%lf, Lon=%lf, Acc=%.2lf rawAcc=%.2lf horConfidence=%d"
             "rawHorConfidence=%d onDemandCpi=%d",
             injectPositionReq.latitude, injectPositionReq.longitude,
             injectPositionReq.horUncCircular, injectPositionReq.rawHorUncCircular,
             injectPositionReq.horConfidence, injectPositionReq.rawHorConfidence,
             injectPositionReq.onDemandCpi);

    LOC_SEND_SYNC_REQ(InjectPosition, INJECT_POSITION, injectPositionReq);

    }));
}

void LocApiV02::injectPosition(const GnssLocationInfoNotification &locationInfo, bool onDemandCpi)
{
    sendMsg(new LocApiMsg([this, locationInfo, onDemandCpi] () {

    qmiLocInjectPositionReqMsgT_v02 injectPositionReq;
    memset(&injectPositionReq, 0, sizeof(injectPositionReq));
    const Location &location = locationInfo.location;

    if (location.timestamp > 0) {
        injectPositionReq.timestampUtc_valid = 1;
        injectPositionReq.timestampUtc = location.timestamp;
    }

    if (LOCATION_HAS_LAT_LONG_BIT & location.flags) {
        injectPositionReq.latitude_valid = 1;
        injectPositionReq.longitude_valid = 1;
        injectPositionReq.latitude = location.latitude;
        injectPositionReq.longitude = location.longitude;
    }

    if (LOCATION_HAS_ACCURACY_BIT & location.flags) {
        injectPositionReq.horUncCircular_valid = 1;
        injectPositionReq.horUncCircular = location.accuracy;
        injectPositionReq.horConfidence_valid = 1;
        injectPositionReq.horConfidence = 68;
        injectPositionReq.rawHorUncCircular_valid = 1;
        injectPositionReq.rawHorUncCircular = location.accuracy;
        injectPositionReq.rawHorConfidence_valid = 1;
        injectPositionReq.rawHorConfidence = 68;

        // We don't wish to advertise accuracy better than 1000 meters to Modem
        if (injectPositionReq.horUncCircular < 1000) {
            injectPositionReq.horUncCircular = 1000;
        }
    }

    if (LOCATION_HAS_ALTITUDE_BIT & location.flags) {
        injectPositionReq.altitudeWrtEllipsoid_valid = 1;
        injectPositionReq.altitudeWrtEllipsoid = location.altitude;
    }

    if (LOCATION_HAS_VERTICAL_ACCURACY_BIT & location.flags) {
        injectPositionReq.vertUnc_valid = 1;
        injectPositionReq.vertUnc = location.verticalAccuracy;
        injectPositionReq.vertConfidence_valid = 1;
        injectPositionReq.vertConfidence = 68;
    }

    // GPS time
    if (locationInfo.gnssSystemTime.gnssSystemTimeSrc == GNSS_LOC_SV_SYSTEM_GPS) {
        injectPositionReq.gpsTime_valid = 1;
        injectPositionReq.gpsTime.gpsWeek =
                locationInfo.gnssSystemTime.u.gpsSystemTime.systemWeek;
        injectPositionReq.gpsTime.gpsTimeOfWeekMs =
                locationInfo.gnssSystemTime.u.gpsSystemTime.systemMsec;
    } else if (locationInfo.gnssSystemTime.gnssSystemTimeSrc == GNSS_LOC_SV_SYSTEM_GALILEO) {
        injectPositionReq.gpsTime_valid = 1;
        injectPositionReq.gpsTime.gpsWeek =
                locationInfo.gnssSystemTime.u.galSystemTime.systemWeek;
        injectPositionReq.gpsTime.gpsTimeOfWeekMs =
                locationInfo.gnssSystemTime.u.gpsSystemTime.systemMsec;
    } else if (locationInfo.gnssSystemTime.gnssSystemTimeSrc == GNSS_LOC_SV_SYSTEM_BDS) {
        injectPositionReq.gpsTime_valid = 1;
        injectPositionReq.gpsTime.gpsWeek =
                locationInfo.gnssSystemTime.u.bdsSystemTime.systemWeek;
        injectPositionReq.gpsTime.gpsTimeOfWeekMs =
                locationInfo.gnssSystemTime.u.bdsSystemTime.systemMsec;
    } else if (locationInfo.gnssSystemTime.gnssSystemTimeSrc == GNSS_LOC_SV_SYSTEM_QZSS) {
        injectPositionReq.gpsTime_valid = 1;
        injectPositionReq.gpsTime.gpsWeek =
                locationInfo.gnssSystemTime.u.qzssSystemTime.systemWeek;
        injectPositionReq.gpsTime.gpsTimeOfWeekMs =
                locationInfo.gnssSystemTime.u.qzssSystemTime.systemMsec;
     } else if (locationInfo.gnssSystemTime.gnssSystemTimeSrc == GNSS_LOC_SV_SYSTEM_GLONASS) {
         if (GNSS_LOCATION_INFO_LEAP_SECONDS_BIT & locationInfo.flags) {
             const GnssGloTimeStructType &gloSystemTime =
                     locationInfo.gnssSystemTime.u.gloSystemTime;
             unsigned long long msecTotal =
                     gloSystemTime.gloFourYear * GLONASS_DAYS_IN_4YEARS * DAY_MSECS +
                     gloSystemTime.gloDays * DAY_MSECS +
                     gloSystemTime.gloMsec;
             // compensate the glonnass msec with difference between GPS time
             msecTotal += (GPS_GLONASS_DAYS_DIFF * DAY_MSECS -
                           GLONASS_UTC_OFFSET_HOURS * 3600 * 1000 +
                           locationInfo.leapSeconds * 1000);
             injectPositionReq.gpsTime_valid = 1;
             injectPositionReq.gpsTime.gpsWeek = msecTotal / WEEK_MSECS;
             injectPositionReq.gpsTime.gpsTimeOfWeekMs = msecTotal % WEEK_MSECS;
         }
    } else if (locationInfo.gnssSystemTime.gnssSystemTimeSrc == GNSS_LOC_SV_SYSTEM_NAVIC) {
        injectPositionReq.gpsTime_valid = 1;
        injectPositionReq.gpsTime.gpsWeek =
                locationInfo.gnssSystemTime.u.navicSystemTime.systemWeek;
        injectPositionReq.gpsTime.gpsTimeOfWeekMs =
                locationInfo.gnssSystemTime.u.navicSystemTime.systemMsec;
    }

    // velocity enu
    if ((GNSS_LOCATION_INFO_EAST_VEL_BIT & locationInfo.flags) &&
        (GNSS_LOCATION_INFO_NORTH_VEL_BIT & locationInfo.flags) &&
        (GNSS_LOCATION_INFO_UP_VEL_BIT & locationInfo.flags)) {
        injectPositionReq.velEnu_valid = 1;
        injectPositionReq.velEnu[0] = locationInfo.eastVelocity;
        injectPositionReq.velEnu[1] = locationInfo.northVelocity;
        injectPositionReq.velEnu[2] = locationInfo.upVelocity;
    }

    // velocity uncertainty enu
    if ((GNSS_LOCATION_INFO_EAST_VEL_UNC_BIT & locationInfo.flags) &&
        (GNSS_LOCATION_INFO_NORTH_VEL_UNC_BIT & locationInfo.flags) &&
        (GNSS_LOCATION_INFO_UP_VEL_UNC_BIT & locationInfo.flags)) {
        injectPositionReq.velUncEnu_valid = 1;
        injectPositionReq.velUncEnu[0] = locationInfo.eastVelocityStdDeviation;
        injectPositionReq.velUncEnu[1] = locationInfo.northVelocityStdDeviation;
        injectPositionReq.velUncEnu[2]  = locationInfo.upVelocityStdDeviation;
    }

    // time uncertainty
    if (GNSS_LOCATION_INFO_TIME_UNC_BIT & locationInfo.flags) {
        injectPositionReq.timeUnc_valid = 1;
        injectPositionReq.timeUnc = locationInfo.timeUncMs;
    }

    // number of SV used info, this replaces expandedGnssSvUsedList as the payload
    // for expandedGnssSvUsedList is too large
    if (GNSS_LOCATION_INFO_NUM_SV_USED_IN_POSITION_BIT & locationInfo.flags) {
        injectPositionReq.numSvInFix = locationInfo.numSvUsedInPosition;
        injectPositionReq.numSvInFix_valid = 1;
    }

    // mark fix as from DRE for modem to distinguish from others
    if (LOCATION_TECHNOLOGY_SENSORS_BIT & locationInfo.location.techMask) {
        injectPositionReq.positionSrc_valid = 1;
        injectPositionReq.positionSrc = eQMI_LOC_POSITION_SRC_DRE_V02;
    }

    if (onDemandCpi) {
        injectPositionReq.onDemandCpi_valid = 1;
        injectPositionReq.onDemandCpi = 1;
    }

    LOC_LOGv("Lat=%lf, Lon=%lf, Acc=%.2lf rawAcc=%.2lf horConfidence=%d"
             "rawHorConfidence=%d onDemandCpi=%d, position src=%d, numSVs=%d",
             injectPositionReq.latitude, injectPositionReq.longitude,
             injectPositionReq.horUncCircular, injectPositionReq.rawHorUncCircular,
             injectPositionReq.horConfidence, injectPositionReq.rawHorConfidence,
             injectPositionReq.onDemandCpi, injectPositionReq.positionSrc,
             injectPositionReq.numSvInFix);

    LOC_SEND_SYNC_REQ(InjectPosition, INJECT_POSITION, injectPositionReq);

    }));
}

/* delete assistance date */
void
LocApiV02::deleteAidingData(const GnssAidingData& data, LocApiResponse *adapterResponse)
{
  sendMsg(new LocApiMsg([this, data, adapterResponse] () {

  static bool isNewApiSupported = true;
  locClientReqUnionType req_union;
  locClientStatusEnumType status = eLOC_CLIENT_FAILURE_UNSUPPORTED;
  LocationError err = LOCATION_ERROR_SUCCESS;

  // Use the new API first
  qmiLocDeleteGNSSServiceDataReqMsgT_v02 delete_gnss_req;
  qmiLocDeleteGNSSServiceDataIndMsgT_v02 delete_gnss_resp;

  memset(&delete_gnss_req, 0, sizeof(delete_gnss_req));
  memset(&delete_gnss_resp, 0, sizeof(delete_gnss_resp));

  if (isNewApiSupported) {
      if (data.deleteAll) {
          delete_gnss_req.deleteAllFlag = true;
      } else {
          if (GNSS_AIDING_DATA_SV_EPHEMERIS_BIT & data.sv.svMask) {
              delete_gnss_req.deleteSatelliteData_valid = 1;
              delete_gnss_req.deleteSatelliteData.deleteSatelliteDataMask |=
                  QMI_LOC_DELETE_DATA_MASK_EPHEMERIS_V02;
          }
          if (GNSS_AIDING_DATA_SV_ALMANAC_BIT & data.sv.svMask) {
              delete_gnss_req.deleteSatelliteData_valid = 1;
              delete_gnss_req.deleteSatelliteData.deleteSatelliteDataMask |=
                  QMI_LOC_DELETE_DATA_MASK_ALMANAC_V02;
          }
          if (GNSS_AIDING_DATA_SV_HEALTH_BIT & data.sv.svMask) {
              delete_gnss_req.deleteSatelliteData_valid = 1;
              delete_gnss_req.deleteSatelliteData.deleteSatelliteDataMask |=
                  QMI_LOC_DELETE_DATA_MASK_SVHEALTH_V02;
          }
          if (GNSS_AIDING_DATA_SV_DIRECTION_BIT & data.sv.svMask) {
              delete_gnss_req.deleteSatelliteData_valid = 1;
              delete_gnss_req.deleteSatelliteData.deleteSatelliteDataMask |=
                  QMI_LOC_DELETE_DATA_MASK_SVDIR_V02;
          }
          if (GNSS_AIDING_DATA_SV_STEER_BIT & data.sv.svMask) {
              delete_gnss_req.deleteSatelliteData_valid = 1;
              delete_gnss_req.deleteSatelliteData.deleteSatelliteDataMask |=
                  QMI_LOC_DELETE_DATA_MASK_SVSTEER_V02;
          }
          if (GNSS_AIDING_DATA_SV_ALMANAC_CORR_BIT & data.sv.svMask) {
              delete_gnss_req.deleteSatelliteData_valid = 1;
              delete_gnss_req.deleteSatelliteData.deleteSatelliteDataMask |=
                  QMI_LOC_DELETE_DATA_MASK_ALM_CORR_V02;
          }
          if (GNSS_AIDING_DATA_SV_BLACKLIST_BIT & data.sv.svMask) {
              delete_gnss_req.deleteSatelliteData_valid = 1;
              delete_gnss_req.deleteSatelliteData.deleteSatelliteDataMask |=
                  QMI_LOC_DELETE_DATA_MASK_BLACKLIST_V02;
          }
          if (GNSS_AIDING_DATA_SV_SA_DATA_BIT & data.sv.svMask) {
              delete_gnss_req.deleteSatelliteData_valid = 1;
              delete_gnss_req.deleteSatelliteData.deleteSatelliteDataMask |=
                  QMI_LOC_DELETE_DATA_MASK_SA_DATA_V02;
          }
          if (GNSS_AIDING_DATA_SV_NO_EXIST_BIT & data.sv.svMask) {
              delete_gnss_req.deleteSatelliteData_valid = 1;
              delete_gnss_req.deleteSatelliteData.deleteSatelliteDataMask |=
                  QMI_LOC_DELETE_DATA_MASK_SV_NO_EXIST_V02;
          }
          if (GNSS_AIDING_DATA_SV_IONOSPHERE_BIT & data.sv.svMask) {
              delete_gnss_req.deleteSatelliteData_valid = 1;
              delete_gnss_req.deleteSatelliteData.deleteSatelliteDataMask |=
                  QMI_LOC_DELETE_DATA_MASK_IONO_V02;
          }
          if (GNSS_AIDING_DATA_SV_TIME_BIT & data.sv.svMask) {
              delete_gnss_req.deleteSatelliteData_valid = 1;
              delete_gnss_req.deleteSatelliteData.deleteSatelliteDataMask |=
                  QMI_LOC_DELETE_DATA_MASK_TIME_V02;
          }
          if (GNSS_AIDING_DATA_SV_MB_DATA & data.sv.svMask) {
              delete_gnss_req.deleteSatelliteData_valid = 1;
              delete_gnss_req.deleteSatelliteData.deleteSatelliteDataMask |=
                  QMI_LOC_DELETE_DATA_MASK_MB_DATA_V02;
          }
          if (delete_gnss_req.deleteSatelliteData_valid) {
              if (GNSS_AIDING_DATA_SV_TYPE_GPS_BIT & data.sv.svTypeMask) {
                  delete_gnss_req.deleteSatelliteData.system |= QMI_LOC_SYSTEM_GPS_V02;
              }
              if (GNSS_AIDING_DATA_SV_TYPE_GLONASS_BIT & data.sv.svTypeMask) {
                  delete_gnss_req.deleteSatelliteData.system |= QMI_LOC_SYSTEM_GLO_V02;
              }
              if (GNSS_AIDING_DATA_SV_TYPE_QZSS_BIT & data.sv.svTypeMask) {
                  delete_gnss_req.deleteSatelliteData.system |= QMI_LOC_SYSTEM_BDS_V02;
              }
              if (GNSS_AIDING_DATA_SV_TYPE_BEIDOU_BIT & data.sv.svTypeMask) {
                  delete_gnss_req.deleteSatelliteData.system |= QMI_LOC_SYSTEM_GAL_V02;
              }
              if (GNSS_AIDING_DATA_SV_TYPE_GALILEO_BIT & data.sv.svTypeMask) {
                  delete_gnss_req.deleteSatelliteData.system |= QMI_LOC_SYSTEM_QZSS_V02;
              }
              if (GNSS_AIDING_DATA_SV_TYPE_NAVIC_BIT & data.sv.svTypeMask) {
                  delete_gnss_req.deleteSatelliteData.system |= QMI_LOC_SYSTEM_NAVIC_V02;
              }
          }

          if (GNSS_AIDING_DATA_COMMON_POSITION_BIT & data.common.mask) {
              delete_gnss_req.deleteCommonDataMask_valid = 1;
              delete_gnss_req.deleteCommonDataMask |= QMI_LOC_DELETE_COMMON_MASK_POS_V02;
          }
          if (GNSS_AIDING_DATA_COMMON_TIME_BIT & data.common.mask) {
              delete_gnss_req.deleteCommonDataMask_valid = 1;
              delete_gnss_req.deleteCommonDataMask |= QMI_LOC_DELETE_COMMON_MASK_TIME_V02;
          }
          if (GNSS_AIDING_DATA_COMMON_UTC_BIT & data.common.mask) {
              delete_gnss_req.deleteCommonDataMask_valid = 1;
              delete_gnss_req.deleteCommonDataMask |= QMI_LOC_DELETE_COMMON_MASK_UTC_V02;
          }
          if (GNSS_AIDING_DATA_COMMON_RTI_BIT & data.common.mask) {
              delete_gnss_req.deleteCommonDataMask_valid = 1;
              delete_gnss_req.deleteCommonDataMask |= QMI_LOC_DELETE_COMMON_MASK_RTI_V02;
          }
          if (GNSS_AIDING_DATA_COMMON_FREQ_BIAS_EST_BIT & data.common.mask) {
              delete_gnss_req.deleteCommonDataMask_valid = 1;
              delete_gnss_req.deleteCommonDataMask |= QMI_LOC_DELETE_COMMON_MASK_FREQ_BIAS_EST_V02;
          }
          if (GNSS_AIDING_DATA_COMMON_CELLDB_BIT & data.common.mask) {
              delete_gnss_req.deleteCellDbDataMask_valid = 1;
              delete_gnss_req.deleteCellDbDataMask =
                  (QMI_LOC_MASK_DELETE_CELLDB_POS_V02 |
                      QMI_LOC_MASK_DELETE_CELLDB_LATEST_GPS_POS_V02 |
                      QMI_LOC_MASK_DELETE_CELLDB_OTA_POS_V02 |
                      QMI_LOC_MASK_DELETE_CELLDB_EXT_REF_POS_V02 |
                      QMI_LOC_MASK_DELETE_CELLDB_TIMETAG_V02 |
                      QMI_LOC_MASK_DELETE_CELLDB_CELLID_V02 |
                      QMI_LOC_MASK_DELETE_CELLDB_CACHED_CELLID_V02 |
                      QMI_LOC_MASK_DELETE_CELLDB_LAST_SRV_CELL_V02 |
                      QMI_LOC_MASK_DELETE_CELLDB_CUR_SRV_CELL_V02 |
                      QMI_LOC_MASK_DELETE_CELLDB_NEIGHBOR_INFO_V02);
          }
      }

      req_union.pDeleteGNSSServiceDataReq = &delete_gnss_req;

      status = locSyncSendReq(QMI_LOC_DELETE_GNSS_SERVICE_DATA_REQ_V02,
                              req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT,
                              QMI_LOC_DELETE_GNSS_SERVICE_DATA_IND_V02,
                              &delete_gnss_resp);

      if (status != eLOC_CLIENT_SUCCESS ||
          eQMI_LOC_SUCCESS_V02 != delete_gnss_resp.status)
      {
          LOC_LOGE("%s:%d]: error! status = %s, delete_resp.status = %s\n",
              __func__, __LINE__,
              loc_get_v02_client_status_name(status),
              loc_get_v02_qmi_status_name(delete_gnss_resp.status));
      }
  }

  if (eLOC_CLIENT_FAILURE_UNSUPPORTED == status ||
      eLOC_CLIENT_FAILURE_INTERNAL == status) {
      // If the new API is not supported we fall back on the old one
      // The error could be eLOC_CLIENT_FAILURE_INTERNAL if
      // QMI_LOC_DELETE_GNSS_SERVICE_DATA_REQ_V02 is not in the .idl file
      LOC_LOGD("%s:%d]: QMI_LOC_DELETE_GNSS_SERVICE_DATA_REQ_V02 not supported"
          "We use QMI_LOC_DELETE_ASSIST_DATA_REQ_V02\n",
          __func__, __LINE__);
      isNewApiSupported = false;

      qmiLocDeleteAssistDataReqMsgT_v02 delete_req;
      qmiLocDeleteAssistDataIndMsgT_v02 delete_resp;

      memset(&delete_req, 0, sizeof(delete_req));
      memset(&delete_resp, 0, sizeof(delete_resp));

      if (data.deleteAll) {
          delete_req.deleteAllFlag = true;
      } else {
          /* to keep track of svInfoList for GPS and GLO*/
          uint32_t curr_sv_len = 0;
          uint32_t curr_sv_idx = 0;
          uint32_t sv_id = 0;

          if ((GNSS_AIDING_DATA_SV_EPHEMERIS_BIT & data.sv.svMask ||
              GNSS_AIDING_DATA_SV_ALMANAC_BIT & data.sv.svMask) &&
              GNSS_AIDING_DATA_SV_TYPE_GPS_BIT & data.sv.svTypeMask) {

              /* do delete for all GPS SV's */
              curr_sv_len += SV_ID_RANGE;

              sv_id = GPS_SV_ID_OFFSET;

              delete_req.deleteSvInfoList_valid = 1;

              delete_req.deleteSvInfoList_len = curr_sv_len;

              LOC_LOGV("%s:%d]: Delete GPS SV info for index %d to %d"
                  "and sv id %d to %d \n",
                  __func__, __LINE__, curr_sv_idx, curr_sv_len - 1,
                  sv_id, sv_id + SV_ID_RANGE - 1);

              for (uint32_t i = curr_sv_idx; i < curr_sv_len; i++, sv_id++) {
                  delete_req.deleteSvInfoList[i].gnssSvId = sv_id;

                  delete_req.deleteSvInfoList[i].system = eQMI_LOC_SV_SYSTEM_GPS_V02;

                  if (GNSS_AIDING_DATA_SV_EPHEMERIS_BIT & data.sv.svMask) {
                      // set ephemeris mask for all GPS SV's
                      delete_req.deleteSvInfoList[i].deleteSvInfoMask |=
                          QMI_LOC_MASK_DELETE_EPHEMERIS_V02;
                  }

                  if (GNSS_AIDING_DATA_SV_ALMANAC_BIT & data.sv.svMask) {
                      delete_req.deleteSvInfoList[i].deleteSvInfoMask |=
                          QMI_LOC_MASK_DELETE_ALMANAC_V02;
                  }
              }
              // increment the current index
              curr_sv_idx += SV_ID_RANGE;

          }

          if (GNSS_AIDING_DATA_COMMON_POSITION_BIT & data.common.mask) {
              delete_req.deleteGnssDataMask_valid = 1;
              delete_req.deleteGnssDataMask |= QMI_LOC_MASK_DELETE_POSITION_V02;
          }
          if (GNSS_AIDING_DATA_COMMON_TIME_BIT & data.common.mask) {
              delete_req.deleteGnssDataMask_valid = 1;
              delete_req.deleteGnssDataMask |= QMI_LOC_MASK_DELETE_TIME_V02;
          }
          if ((GNSS_AIDING_DATA_SV_IONOSPHERE_BIT & data.sv.svMask) &&
              (GNSS_AIDING_DATA_SV_TYPE_GPS_BIT & data.sv.svTypeMask)) {
              delete_req.deleteGnssDataMask_valid = 1;
              delete_req.deleteGnssDataMask |= QMI_LOC_MASK_DELETE_IONO_V02;
          }
          if (GNSS_AIDING_DATA_COMMON_UTC_BIT & data.common.mask)
          {
              delete_req.deleteGnssDataMask_valid = 1;
              delete_req.deleteGnssDataMask |= QMI_LOC_MASK_DELETE_UTC_V02;
          }
          if ((GNSS_AIDING_DATA_SV_HEALTH_BIT & data.sv.svMask) &&
              (GNSS_AIDING_DATA_SV_TYPE_GPS_BIT & data.sv.svTypeMask)) {
              delete_req.deleteGnssDataMask_valid = 1;
              delete_req.deleteGnssDataMask |= QMI_LOC_MASK_DELETE_HEALTH_V02;
          }
          if ((GNSS_AIDING_DATA_SV_DIRECTION_BIT & data.sv.svMask) &&
              (GNSS_AIDING_DATA_SV_TYPE_GPS_BIT & data.sv.svTypeMask)) {
              delete_req.deleteGnssDataMask_valid = 1;
              delete_req.deleteGnssDataMask |= QMI_LOC_MASK_DELETE_GPS_SVDIR_V02;
          }
          if ((GNSS_AIDING_DATA_SV_SA_DATA_BIT & data.sv.svMask) &&
              (GNSS_AIDING_DATA_SV_TYPE_GPS_BIT & data.sv.svTypeMask)) {
              delete_req.deleteGnssDataMask_valid = 1;
              delete_req.deleteGnssDataMask |= QMI_LOC_MASK_DELETE_SADATA_V02;
          }
          if (GNSS_AIDING_DATA_COMMON_RTI_BIT & data.common.mask) {
              delete_req.deleteGnssDataMask_valid = 1;
              delete_req.deleteGnssDataMask |= QMI_LOC_MASK_DELETE_RTI_V02;
          }
          if (GNSS_AIDING_DATA_COMMON_CELLDB_BIT & data.common.mask) {
              delete_req.deleteCellDbDataMask_valid = 1;
              delete_req.deleteCellDbDataMask =
                  (QMI_LOC_MASK_DELETE_CELLDB_POS_V02 |
                      QMI_LOC_MASK_DELETE_CELLDB_LATEST_GPS_POS_V02 |
                      QMI_LOC_MASK_DELETE_CELLDB_OTA_POS_V02 |
                      QMI_LOC_MASK_DELETE_CELLDB_EXT_REF_POS_V02 |
                      QMI_LOC_MASK_DELETE_CELLDB_TIMETAG_V02 |
                      QMI_LOC_MASK_DELETE_CELLDB_CELLID_V02 |
                      QMI_LOC_MASK_DELETE_CELLDB_CACHED_CELLID_V02 |
                      QMI_LOC_MASK_DELETE_CELLDB_LAST_SRV_CELL_V02 |
                      QMI_LOC_MASK_DELETE_CELLDB_CUR_SRV_CELL_V02 |
                      QMI_LOC_MASK_DELETE_CELLDB_NEIGHBOR_INFO_V02);

          }
      }

      req_union.pDeleteAssistDataReq = &delete_req;

      status = locSyncSendReq(QMI_LOC_DELETE_ASSIST_DATA_REQ_V02,
                              req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT,
                              QMI_LOC_DELETE_ASSIST_DATA_IND_V02,
                              &delete_resp);

      if (status != eLOC_CLIENT_SUCCESS ||
          eQMI_LOC_SUCCESS_V02 != delete_resp.status)
      {
          LOC_LOGE("%s:%d]: error! status = %s, delete_resp.status = %s\n",
              __func__, __LINE__,
              loc_get_v02_client_status_name(status),
              loc_get_v02_qmi_status_name(delete_resp.status));
          err = LOCATION_ERROR_GENERAL_FAILURE;
      }
  }

  if (adapterResponse != NULL) {
      adapterResponse->returnToSender(err);
  }
  }));
}

/* send NI user repsonse to the engine */
void
LocApiV02::informNiResponse(GnssNiResponse userResponse, const void* passThroughData)
{
    sendMsg(new LocApiMsg([this, userResponse, passThroughData] () {

        LocationError err = LOCATION_ERROR_SUCCESS;
        locClientReqUnionType req_union;
        locClientStatusEnumType status;
        qmiLocNiUserRespReqMsgT_v02 ni_resp;
        qmiLocNiUserRespIndMsgT_v02 ni_resp_ind;

        qmiLocEventNiNotifyVerifyReqIndMsgT_v02 *request_pass_back =
            (qmiLocEventNiNotifyVerifyReqIndMsgT_v02 *)passThroughData;

        memset(&ni_resp,0, sizeof(ni_resp));

        memset(&ni_resp_ind,0, sizeof(ni_resp_ind));

        switch (userResponse) {
        case GNSS_NI_RESPONSE_ACCEPT:
            ni_resp.userResp = eQMI_LOC_NI_LCS_NOTIFY_VERIFY_ACCEPT_V02;
            break;
        case GNSS_NI_RESPONSE_DENY:
            ni_resp.userResp = eQMI_LOC_NI_LCS_NOTIFY_VERIFY_DENY_V02;
            break;
        case GNSS_NI_RESPONSE_NO_RESPONSE:
            ni_resp.userResp = eQMI_LOC_NI_LCS_NOTIFY_VERIFY_NORESP_V02;
            break;
        default:
            err = LOCATION_ERROR_INVALID_PARAMETER;
            free((void *)passThroughData);
            return;
        }

        LOC_LOGv("NI response: %d", ni_resp.userResp);

        ni_resp.notificationType = request_pass_back->notificationType;

        // copy SUPL payload from request
        if (1 == request_pass_back->NiSuplInd_valid) {
            ni_resp.NiSuplPayload_valid = 1;
            memcpy(&(ni_resp.NiSuplPayload),
                   &(request_pass_back->NiSuplInd),
                   sizeof(qmiLocNiSuplNotifyVerifyStructT_v02));
        }
        // should this be an "else if"?? we don't need to decide

        // copy UMTS-CP payload from request
        if (1 == request_pass_back->NiUmtsCpInd_valid) {
            ni_resp.NiUmtsCpPayload_valid = 1;
            memcpy(&(ni_resp.NiUmtsCpPayload),
                   &(request_pass_back->NiUmtsCpInd),
                   sizeof(qmiLocNiUmtsCpNotifyVerifyStructT_v02));
        }

        //copy Vx payload from the request
        if (1 == request_pass_back->NiVxInd_valid) {
            ni_resp.NiVxPayload_valid = 1;
            memcpy(&(ni_resp.NiVxPayload),
                   &(request_pass_back->NiVxInd),
                   sizeof(qmiLocNiVxNotifyVerifyStructT_v02));
        }

        // copy Vx service interaction payload from the request
        if (1 == request_pass_back->NiVxServiceInteractionInd_valid) {
            ni_resp.NiVxServiceInteractionPayload_valid = 1;
            memcpy(&(ni_resp.NiVxServiceInteractionPayload),
                   &(request_pass_back->NiVxServiceInteractionInd),
                   sizeof(qmiLocNiVxServiceInteractionStructT_v02));
        }

        // copy Network Initiated SUPL Version 2 Extension
        if (1 == request_pass_back->NiSuplVer2ExtInd_valid) {
            ni_resp.NiSuplVer2ExtPayload_valid = 1;
            memcpy(&(ni_resp.NiSuplVer2ExtPayload),
                   &(request_pass_back->NiSuplVer2ExtInd),
                   sizeof(qmiLocNiSuplVer2ExtStructT_v02));
        }

        // copy SUPL Emergency Notification
        if (request_pass_back->suplEmergencyNotification_valid) {
            ni_resp.suplEmergencyNotification_valid = 1;
            memcpy(&(ni_resp.suplEmergencyNotification),
                   &(request_pass_back->suplEmergencyNotification),
                   sizeof(qmiLocEmergencyNotificationStructT_v02));
        }

        req_union.pNiUserRespReq = &ni_resp;

        status = locSyncSendReq(QMI_LOC_NI_USER_RESPONSE_REQ_V02,
                                req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT,
                                QMI_LOC_NI_USER_RESPONSE_IND_V02,
                                &ni_resp_ind);

        if (status != eLOC_CLIENT_SUCCESS ||
            eQMI_LOC_SUCCESS_V02 != ni_resp_ind.status) {

            LOC_LOGe("error! status = %s, ni_resp_ind.status = %s",
                     loc_get_v02_client_status_name(status),
                     loc_get_v02_qmi_status_name(ni_resp_ind.status));
            err = LOCATION_ERROR_GENERAL_FAILURE;
        }

        free((void *)passThroughData);
    }));
}

void
LocApiV02::registerMasterClient()
{
  LocationError err = LOCATION_ERROR_SUCCESS;
  locClientReqUnionType req_union;
  locClientStatusEnumType status;
  qmiLocRegisterMasterClientReqMsgT_v02 reg_master_client_req;
  qmiLocRegisterMasterClientIndMsgT_v02 reg_master_client_ind;

  memset(&reg_master_client_req, 0, sizeof(reg_master_client_req));
  memset(&reg_master_client_ind, 0, sizeof(reg_master_client_ind));

  reg_master_client_req.key = 0xBAABCDEF;

  req_union.pRegisterMasterClientReq = &reg_master_client_req;

  status = locSyncSendReq(QMI_LOC_REGISTER_MASTER_CLIENT_REQ_V02,
                          req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT,
                          QMI_LOC_REGISTER_MASTER_CLIENT_IND_V02,
                          &reg_master_client_ind);

  if (eLOC_CLIENT_SUCCESS != status ||
      eQMI_LOC_REGISTER_MASTER_CLIENT_SUCCESS_V02 != reg_master_client_ind.status) {
    LOC_LOGw ("error status = %s, reg_master_client_ind.status = %s",
              loc_get_v02_client_status_name(status),
              loc_get_v02_qmi_reg_mk_status_name(reg_master_client_ind.status));
    if (eLOC_CLIENT_FAILURE_INVALID_MESSAGE_ID == status ||
        eLOC_CLIENT_FAILURE_UNSUPPORTED == status) {
      mMasterRegisterNotSupported = true;
    } else {
      mMasterRegisterNotSupported = false;
    }
    LOC_LOGv("mMasterRegisterNotSupported = %d", mMasterRegisterNotSupported);
    err = LOCATION_ERROR_GENERAL_FAILURE;
  }
}

/* Set UMTs SLP server URL */
LocationError
LocApiV02::setServerSync(const char* url, int len, LocServerType type)
{
  LocationError err = LOCATION_ERROR_SUCCESS;
  locClientReqUnionType req_union;
  locClientStatusEnumType status;
  qmiLocSetServerReqMsgT_v02 set_server_req;
  qmiLocSetServerIndMsgT_v02 set_server_ind;

  if(len < 0 || (size_t)len > sizeof(set_server_req.urlAddr))
  {
    LOC_LOGe("len = %d greater than max allowed url length", len);

    return LOCATION_ERROR_INVALID_PARAMETER;
  }

  memset(&set_server_req, 0, sizeof(set_server_req));
  memset(&set_server_ind, 0, sizeof(set_server_ind));

  LOC_LOGd("url = %s, len = %d type=%d", url, len, type);

  if (LOC_AGPS_MO_SUPL_SERVER == type) {
      set_server_req.serverType = eQMI_LOC_SERVER_TYPE_CUSTOM_SLP_V02;
  } else {
      set_server_req.serverType = eQMI_LOC_SERVER_TYPE_UMTS_SLP_V02;
  }

  set_server_req.urlAddr_valid = 1;

  strlcpy(set_server_req.urlAddr, url, sizeof(set_server_req.urlAddr));

  req_union.pSetServerReq = &set_server_req;

  status = locSyncSendReq(QMI_LOC_SET_SERVER_REQ_V02,
                          req_union, LOC_ENGINE_SYNC_REQUEST_LONG_TIMEOUT,
                          QMI_LOC_SET_SERVER_IND_V02,
                          &set_server_ind);

  if (status != eLOC_CLIENT_SUCCESS ||
         eQMI_LOC_SUCCESS_V02 != set_server_ind.status)
  {
    LOC_LOGe ("error status = %s, set_server_ind.status = %s",
              loc_get_v02_client_status_name(status),
              loc_get_v02_qmi_status_name(set_server_ind.status));
    err = LOCATION_ERROR_GENERAL_FAILURE;
  }

  return err;
}

LocationError
LocApiV02::setServerSync(unsigned int ip, int port, LocServerType type)
{
  LocationError err = LOCATION_ERROR_SUCCESS;
  locClientReqUnionType req_union;
  locClientStatusEnumType status;
  qmiLocSetServerReqMsgT_v02 set_server_req;
  qmiLocSetServerIndMsgT_v02 set_server_ind;
  qmiLocServerTypeEnumT_v02 set_server_cmd;

  switch (type) {
  case LOC_AGPS_MPC_SERVER:
      set_server_cmd = eQMI_LOC_SERVER_TYPE_CDMA_MPC_V02;
      break;
  case LOC_AGPS_CUSTOM_PDE_SERVER:
      set_server_cmd = eQMI_LOC_SERVER_TYPE_CUSTOM_PDE_V02;
      break;
  default:
      set_server_cmd = eQMI_LOC_SERVER_TYPE_CDMA_PDE_V02;
      break;
  }

  memset(&set_server_req, 0, sizeof(set_server_req));
  memset(&set_server_ind, 0, sizeof(set_server_ind));

  LOC_LOGD("%s:%d]:, ip = %u, port = %d\n", __func__, __LINE__, ip, port);

  set_server_req.serverType = set_server_cmd;
  set_server_req.ipv4Addr_valid = 1;
  set_server_req.ipv4Addr.addr = ip;
  set_server_req.ipv4Addr.port = port;

  req_union.pSetServerReq = &set_server_req;

  status = locSyncSendReq(QMI_LOC_SET_SERVER_REQ_V02,
                          req_union, LOC_ENGINE_SYNC_REQUEST_LONG_TIMEOUT,
                          QMI_LOC_SET_SERVER_IND_V02,
                          &set_server_ind);

  if (status != eLOC_CLIENT_SUCCESS ||
      eQMI_LOC_SUCCESS_V02 != set_server_ind.status)
  {
    LOC_LOGE ("%s:%d]: error status = %s, set_server_ind.status = %s\n",
              __func__,__LINE__,
              loc_get_v02_client_status_name(status),
              loc_get_v02_qmi_status_name(set_server_ind.status));
    err = LOCATION_ERROR_GENERAL_FAILURE;
  }

  return err;
}

void LocApiV02 :: atlOpenStatus(
  int handle, int is_succ, char* apn, uint32_t apnLen, AGpsBearerType bear,
  LocAGpsType /*agpsType*/, LocApnTypeMask apnTypeMask)
{
  sendMsg(new LocApiMsg([this, handle, is_succ,
                        apnStr=std::string(apn, apnLen),
                        bear, apnTypeMask] () {

  locClientStatusEnumType result = eLOC_CLIENT_SUCCESS;
  locClientReqUnionType req_union;
  qmiLocInformLocationServerConnStatusReqMsgT_v02 conn_status_req;
  qmiLocInformLocationServerConnStatusIndMsgT_v02 conn_status_ind;

  LOC_LOGd("ATL open handle = %d, is_succ = %d, APN = [%s], bearer = %d, "
           "apnTypeMask 0x%X" PRIx32, handle, is_succ, apnStr.c_str(),
           bear, apnTypeMask);

  memset(&conn_status_req, 0, sizeof(conn_status_req));
  memset(&conn_status_ind, 0, sizeof(conn_status_ind));

        // Fill in data
  conn_status_req.connHandle = handle;

  conn_status_req.requestType = eQMI_LOC_SERVER_REQUEST_OPEN_V02;

  if(is_succ)
  {
    conn_status_req.statusType = eQMI_LOC_SERVER_REQ_STATUS_SUCCESS_V02;

    if(!apnStr.empty()) {
        strlcpy(conn_status_req.apnProfile.apnName, apnStr.c_str(),
                sizeof(conn_status_req.apnProfile.apnName) );
    }

    switch(bear)
    {
    case AGPS_APN_BEARER_IPV4:
        conn_status_req.apnProfile.pdnType =
            eQMI_LOC_APN_PROFILE_PDN_TYPE_IPV4_V02;
        conn_status_req.apnProfile_valid = 1;
        break;

    case AGPS_APN_BEARER_IPV6:
        conn_status_req.apnProfile.pdnType =
            eQMI_LOC_APN_PROFILE_PDN_TYPE_IPV6_V02;
        conn_status_req.apnProfile_valid = 1;
        break;

    case AGPS_APN_BEARER_IPV4V6:
        conn_status_req.apnProfile.pdnType =
            eQMI_LOC_APN_PROFILE_PDN_TYPE_IPV4V6_V02;
        conn_status_req.apnProfile_valid = 1;
        break;

    case AGPS_APN_BEARER_INVALID:
        conn_status_req.apnProfile_valid = 0;
        break;

    default:
        LOC_LOGE("%s:%d]:invalid bearer type\n",__func__,__LINE__);
        conn_status_req.apnProfile_valid = 0;
        return;
    }

    // Populate apnTypeMask
    if (0 != apnTypeMask) {
        conn_status_req.apnTypeMask_valid = true;
        conn_status_req.apnTypeMask = convertLocApnTypeMask(apnTypeMask);
    }

  }
  else
  {
    conn_status_req.statusType = eQMI_LOC_SERVER_REQ_STATUS_FAILURE_V02;
  }

  req_union.pInformLocationServerConnStatusReq = &conn_status_req;

  result = locSyncSendReq(QMI_LOC_INFORM_LOCATION_SERVER_CONN_STATUS_REQ_V02,
                          req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT,
                          QMI_LOC_INFORM_LOCATION_SERVER_CONN_STATUS_IND_V02,
                          &conn_status_ind);

  if(result != eLOC_CLIENT_SUCCESS ||
     eQMI_LOC_SUCCESS_V02 != conn_status_ind.status)
  {
    LOC_LOGE ("%s:%d]: Error status = %s, ind..status = %s ",
              __func__, __LINE__,
              loc_get_v02_client_status_name(result),
              loc_get_v02_qmi_status_name(conn_status_ind.status));
  }

  }));
}


/* close atl connection */
void LocApiV02 :: atlCloseStatus(int handle, int is_succ)
{
  sendMsg(new LocApiMsg([this, handle, is_succ] () {

  locClientStatusEnumType result = eLOC_CLIENT_SUCCESS;
  locClientReqUnionType req_union;
  qmiLocInformLocationServerConnStatusReqMsgT_v02 conn_status_req;
  qmiLocInformLocationServerConnStatusIndMsgT_v02 conn_status_ind;

  LOC_LOGD("%s:%d]: ATL close handle = %d, is_succ = %d\n",
                 __func__, __LINE__,  handle, is_succ);

  memset(&conn_status_req, 0, sizeof(conn_status_req));
  memset(&conn_status_ind, 0, sizeof(conn_status_ind));

        // Fill in data
  conn_status_req.connHandle = handle;

  conn_status_req.requestType = eQMI_LOC_SERVER_REQUEST_CLOSE_V02;

  if(is_succ)
  {
    conn_status_req.statusType = eQMI_LOC_SERVER_REQ_STATUS_SUCCESS_V02;
  }
  else
  {
    conn_status_req.statusType = eQMI_LOC_SERVER_REQ_STATUS_FAILURE_V02;
  }

  req_union.pInformLocationServerConnStatusReq = &conn_status_req;

  result = locSyncSendReq(QMI_LOC_INFORM_LOCATION_SERVER_CONN_STATUS_REQ_V02,
                          req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT,
                          QMI_LOC_INFORM_LOCATION_SERVER_CONN_STATUS_IND_V02,
                          &conn_status_ind);

  if(result != eLOC_CLIENT_SUCCESS ||
     eQMI_LOC_SUCCESS_V02 != conn_status_ind.status)
  {
    LOC_LOGE ("%s:%d]: Error status = %s, ind..status = %s ",
              __func__, __LINE__,
              loc_get_v02_client_status_name(result),
              loc_get_v02_qmi_status_name(conn_status_ind.status));
  }
  }));
}

/* set the SUPL version */
LocationError
LocApiV02::setSUPLVersionSync(GnssConfigSuplVersion version)
{
  LocationError err = LOCATION_ERROR_SUCCESS;
  locClientStatusEnumType result = eLOC_CLIENT_SUCCESS;
  locClientReqUnionType req_union;

  qmiLocSetProtocolConfigParametersReqMsgT_v02 supl_config_req;
  qmiLocSetProtocolConfigParametersIndMsgT_v02 supl_config_ind;

  LOC_LOGD("%s:%d]: supl version = %d\n",  __func__, __LINE__, version);


  memset(&supl_config_req, 0, sizeof(supl_config_req));
  memset(&supl_config_ind, 0, sizeof(supl_config_ind));

  supl_config_req.suplVersion_valid = 1;

  switch (version) {
    case GNSS_CONFIG_SUPL_VERSION_2_0_4:
      supl_config_req.suplVersion = eQMI_LOC_SUPL_VERSION_2_0_4_V02;
      break;
    case GNSS_CONFIG_SUPL_VERSION_2_0_2:
      supl_config_req.suplVersion = eQMI_LOC_SUPL_VERSION_2_0_2_V02;
      break;
    case GNSS_CONFIG_SUPL_VERSION_2_0_0:
      supl_config_req.suplVersion = eQMI_LOC_SUPL_VERSION_2_0_V02;
      break;
    case GNSS_CONFIG_SUPL_VERSION_1_0_0:
    default:
      supl_config_req.suplVersion =  eQMI_LOC_SUPL_VERSION_1_0_V02;
      break;
  }

  req_union.pSetProtocolConfigParametersReq = &supl_config_req;

  result = locSyncSendReq(QMI_LOC_SET_PROTOCOL_CONFIG_PARAMETERS_REQ_V02,
                          req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT,
                          QMI_LOC_SET_PROTOCOL_CONFIG_PARAMETERS_IND_V02,
                          &supl_config_ind);

  if(result != eLOC_CLIENT_SUCCESS ||
     eQMI_LOC_SUCCESS_V02 != supl_config_ind.status)
  {
    LOC_LOGE ("%s:%d]: Error status = %s, ind..status = %s ",
              __func__, __LINE__,
              loc_get_v02_client_status_name(result),
              loc_get_v02_qmi_status_name(supl_config_ind.status));
     err = LOCATION_ERROR_GENERAL_FAILURE;
  }

  return err;
}

/* set the NMEA types mask */
enum loc_api_adapter_err LocApiV02 :: setNMEATypesSync(uint32_t typesMask)
{
  locClientStatusEnumType result = eLOC_CLIENT_SUCCESS;
  locClientReqUnionType req_union;

  qmiLocSetNmeaTypesReqMsgT_v02 setNmeaTypesReqMsg;
  qmiLocSetNmeaTypesIndMsgT_v02 setNmeaTypesIndMsg;

  LOC_LOGD(" %s:%d]: setNMEATypes, mask = 0x%X", __func__, __LINE__, typesMask);

  if (typesMask != mNmeaMask) {
      memset(&setNmeaTypesReqMsg, 0, sizeof(setNmeaTypesReqMsg));
      memset(&setNmeaTypesIndMsg, 0, sizeof(setNmeaTypesIndMsg));

      setNmeaTypesReqMsg.nmeaSentenceType = typesMask;

      req_union.pSetNmeaTypesReq = &setNmeaTypesReqMsg;

      LOC_LOGD(" %s:%d]: Setting mask = 0x%X", __func__, __LINE__, typesMask);
      result = locSyncSendReq(QMI_LOC_SET_NMEA_TYPES_REQ_V02,
                              req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT,
                              QMI_LOC_SET_NMEA_TYPES_IND_V02,
                              &setNmeaTypesIndMsg);

      // if success
      if (result != eLOC_CLIENT_SUCCESS)
      {
          LOC_LOGE("%s:%d]: Error status = %s, ind..status = %s ",
                   __func__, __LINE__,
                   loc_get_v02_client_status_name(result),
                   loc_get_v02_qmi_status_name(setNmeaTypesIndMsg.status));
      }
      mNmeaMask = typesMask;
  }

  return convertErr(result);
}

/* set the configuration for LTE positioning profile (LPP) */
LocationError
LocApiV02::setLPPConfigSync(GnssConfigLppProfileMask profileMask)
{
  LocationError err = LOCATION_ERROR_SUCCESS;
  locClientStatusEnumType result = eLOC_CLIENT_SUCCESS;
  locClientReqUnionType req_union;
  qmiLocSetProtocolConfigParametersReqMsgT_v02 lpp_config_req;
  qmiLocSetProtocolConfigParametersIndMsgT_v02 lpp_config_ind;

  LOC_LOGD("%s:%d]: lpp profile = %u",  __func__, __LINE__, profileMask);

  memset(&lpp_config_req, 0, sizeof(lpp_config_req));
  memset(&lpp_config_ind, 0, sizeof(lpp_config_ind));

  lpp_config_req.lppConfig_valid = 1;
  if (profileMask & GNSS_CONFIG_LPP_PROFILE_USER_PLANE_BIT) {
      lpp_config_req.lppConfig |= QMI_LOC_LPP_CONFIG_ENABLE_USER_PLANE_V02;
  }
  if (profileMask & GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE_BIT) {
      lpp_config_req.lppConfig |= QMI_LOC_LPP_CONFIG_ENABLE_CONTROL_PLANE_V02;
  }
  if (profileMask & GNSS_CONFIG_LPP_PROFILE_USER_PLANE_OVER_NR5G_SA_BIT) {
      lpp_config_req.lppConfig |= QMI_LOC_LPP_CONFIG_ENABLE_USER_PLANE_OVER_NR5G_SA_V02;
  }
  if (profileMask & GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE_OVER_NR5G_SA_BIT) {
      lpp_config_req.lppConfig |= QMI_LOC_LPP_CONFIG_ENABLE_CONTROL_PLANE_OVER_NR5G_SA_V02;
  }

  req_union.pSetProtocolConfigParametersReq = &lpp_config_req;

  result = locSyncSendReq(QMI_LOC_SET_PROTOCOL_CONFIG_PARAMETERS_REQ_V02,
                          req_union, LOC_ENGINE_SYNC_REQUEST_LONG_TIMEOUT,
                          QMI_LOC_SET_PROTOCOL_CONFIG_PARAMETERS_IND_V02,
                          &lpp_config_ind);

  if(result != eLOC_CLIENT_SUCCESS ||
     eQMI_LOC_SUCCESS_V02 != lpp_config_ind.status)
  {
    LOC_LOGE ("%s:%d]: Error status = %s, ind..status = %s ",
              __func__, __LINE__,
              loc_get_v02_client_status_name(result),
              loc_get_v02_qmi_status_name(lpp_config_ind.status));
     err = LOCATION_ERROR_GENERAL_FAILURE;
  }

  return err;
}


/* set the Sensor Properties */
enum loc_api_adapter_err LocApiV02 :: setSensorPropertiesSync(
        bool gyroBiasVarianceRandomWalk_valid, float gyroBiasVarianceRandomWalk,
        bool accelBiasVarianceRandomWalk_valid, float accelBiasVarianceRandomWalk,
        bool angleBiasVarianceRandomWalk_valid, float angleBiasVarianceRandomWalk,
        bool rateBiasVarianceRandomWalk_valid, float rateBiasVarianceRandomWalk,
        bool velocityBiasVarianceRandomWalk_valid, float velocityBiasVarianceRandomWalk)
{
  locClientStatusEnumType result = eLOC_CLIENT_SUCCESS;
  locClientReqUnionType req_union;

  qmiLocSetSensorPropertiesReqMsgT_v02 sensor_prop_req;
  qmiLocSetSensorPropertiesIndMsgT_v02 sensor_prop_ind;

  LOC_LOGI("%s:%d]: sensors prop: gyroBiasRandomWalk = %f, accelRandomWalk = %f, "
           "angleRandomWalk = %f, rateRandomWalk = %f, velocityRandomWalk = %f\n",
                 __func__, __LINE__, gyroBiasVarianceRandomWalk, accelBiasVarianceRandomWalk,
           angleBiasVarianceRandomWalk, rateBiasVarianceRandomWalk, velocityBiasVarianceRandomWalk);

  memset(&sensor_prop_req, 0, sizeof(sensor_prop_req));
  memset(&sensor_prop_ind, 0, sizeof(sensor_prop_ind));

  /* Set the validity bit and value for each sensor property */
  sensor_prop_req.gyroBiasVarianceRandomWalk_valid = gyroBiasVarianceRandomWalk_valid;
  sensor_prop_req.gyroBiasVarianceRandomWalk = gyroBiasVarianceRandomWalk;

  sensor_prop_req.accelerationRandomWalkSpectralDensity_valid = accelBiasVarianceRandomWalk_valid;
  sensor_prop_req.accelerationRandomWalkSpectralDensity = accelBiasVarianceRandomWalk;

  sensor_prop_req.angleRandomWalkSpectralDensity_valid = angleBiasVarianceRandomWalk_valid;
  sensor_prop_req.angleRandomWalkSpectralDensity = angleBiasVarianceRandomWalk;

  sensor_prop_req.rateRandomWalkSpectralDensity_valid = rateBiasVarianceRandomWalk_valid;
  sensor_prop_req.rateRandomWalkSpectralDensity = rateBiasVarianceRandomWalk;

  sensor_prop_req.velocityRandomWalkSpectralDensity_valid = velocityBiasVarianceRandomWalk_valid;
  sensor_prop_req.velocityRandomWalkSpectralDensity = velocityBiasVarianceRandomWalk;

  req_union.pSetSensorPropertiesReq = &sensor_prop_req;

  result = locSyncSendReq(QMI_LOC_SET_SENSOR_PROPERTIES_REQ_V02,
                          req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT,
                          QMI_LOC_SET_SENSOR_PROPERTIES_IND_V02,
                          &sensor_prop_ind);

  if(result != eLOC_CLIENT_SUCCESS ||
     eQMI_LOC_SUCCESS_V02 != sensor_prop_ind.status)
  {
    LOC_LOGE ("%s:%d]: Error status = %s, ind..status = %s ",
              __func__, __LINE__,
              loc_get_v02_client_status_name(result),
              loc_get_v02_qmi_status_name(sensor_prop_ind.status));
  }

  return convertErr(result);
}

/* set the Sensor Performance Config */
enum loc_api_adapter_err LocApiV02 :: setSensorPerfControlConfigSync(int controlMode,
        int accelSamplesPerBatch, int accelBatchesPerSec,
        int gyroSamplesPerBatch, int gyroBatchesPerSec,
        int accelSamplesPerBatchHigh, int accelBatchesPerSecHigh,
        int gyroSamplesPerBatchHigh, int gyroBatchesPerSecHigh,
        int algorithmConfig)
{
  locClientStatusEnumType result = eLOC_CLIENT_SUCCESS;
  locClientReqUnionType req_union;

  qmiLocSetSensorPerformanceControlConfigReqMsgT_v02 sensor_perf_config_req;
  qmiLocSetSensorPerformanceControlConfigIndMsgT_v02 sensor_perf_config_ind;

  LOC_LOGD("%s:%d]: Sensor Perf Control Config (performanceControlMode)(%u) "
                "accel(#smp,#batches) (%u,%u) gyro(#smp,#batches) (%u,%u) "
                "accel_high(#smp,#batches) (%u,%u) gyro_high(#smp,#batches) (%u,%u) "
                "algorithmConfig(%u)\n",
                __FUNCTION__,
                __LINE__,
                controlMode,
                accelSamplesPerBatch,
                accelBatchesPerSec,
                gyroSamplesPerBatch,
                gyroBatchesPerSec,
                accelSamplesPerBatchHigh,
                accelBatchesPerSecHigh,
                gyroSamplesPerBatchHigh,
                gyroBatchesPerSecHigh,
                algorithmConfig
                );

  memset(&sensor_perf_config_req, 0, sizeof(sensor_perf_config_req));
  memset(&sensor_perf_config_ind, 0, sizeof(sensor_perf_config_ind));

  sensor_perf_config_req.performanceControlMode_valid = (controlMode == 2) ? 0 : 1;
  sensor_perf_config_req.performanceControlMode = (qmiLocSensorPerformanceControlModeEnumT_v02)controlMode;
  sensor_perf_config_req.accelSamplingSpec_valid = 1;
  sensor_perf_config_req.accelSamplingSpec.batchesPerSecond = accelBatchesPerSec;
  sensor_perf_config_req.accelSamplingSpec.samplesPerBatch = accelSamplesPerBatch;
  sensor_perf_config_req.gyroSamplingSpec_valid = 1;
  sensor_perf_config_req.gyroSamplingSpec.batchesPerSecond = gyroBatchesPerSec;
  sensor_perf_config_req.gyroSamplingSpec.samplesPerBatch = gyroSamplesPerBatch;
  sensor_perf_config_req.accelSamplingSpecHigh_valid = 1;
  sensor_perf_config_req.accelSamplingSpecHigh.batchesPerSecond = accelBatchesPerSecHigh;
  sensor_perf_config_req.accelSamplingSpecHigh.samplesPerBatch = accelSamplesPerBatchHigh;
  sensor_perf_config_req.gyroSamplingSpecHigh_valid = 1;
  sensor_perf_config_req.gyroSamplingSpecHigh.batchesPerSecond = gyroBatchesPerSecHigh;
  sensor_perf_config_req.gyroSamplingSpecHigh.samplesPerBatch = gyroSamplesPerBatchHigh;
  sensor_perf_config_req.algorithmConfig_valid = 1;
  sensor_perf_config_req.algorithmConfig = algorithmConfig;

  req_union.pSetSensorPerformanceControlConfigReq = &sensor_perf_config_req;

  result = locSyncSendReq(QMI_LOC_SET_SENSOR_PERFORMANCE_CONTROL_CONFIGURATION_REQ_V02,
                          req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT,
                          QMI_LOC_SET_SENSOR_PERFORMANCE_CONTROL_CONFIGURATION_IND_V02,
                          &sensor_perf_config_ind);

  if(result != eLOC_CLIENT_SUCCESS ||
     eQMI_LOC_SUCCESS_V02 != sensor_perf_config_ind.status)
  {
    LOC_LOGE ("%s:%d]: Error status = %s, ind..status = %s ",
              __func__, __LINE__,
              loc_get_v02_client_status_name(result),
              loc_get_v02_qmi_status_name(sensor_perf_config_ind.status));
  }

  return convertErr(result);
}

/* set the Positioning Protocol on A-GLONASS system */
LocationError
LocApiV02::setAGLONASSProtocolSync(GnssConfigAGlonassPositionProtocolMask aGlonassProtocol)
{
  LocationError err = LOCATION_ERROR_SUCCESS;
  locClientStatusEnumType result = eLOC_CLIENT_SUCCESS;
  locClientReqUnionType req_union;
  qmiLocSetProtocolConfigParametersReqMsgT_v02 aGlonassProtocol_req;
  qmiLocSetProtocolConfigParametersIndMsgT_v02 aGlonassProtocol_ind;

  memset(&aGlonassProtocol_req, 0, sizeof(aGlonassProtocol_req));
  memset(&aGlonassProtocol_ind, 0, sizeof(aGlonassProtocol_ind));

  aGlonassProtocol_req.assistedGlonassProtocolMask_valid = 1;
  if (GNSS_CONFIG_RRC_CONTROL_PLANE_BIT & aGlonassProtocol) {
      aGlonassProtocol_req.assistedGlonassProtocolMask |=
          QMI_LOC_ASSISTED_GLONASS_PROTOCOL_MASK_RRC_CP_V02 ;
  }
  if (GNSS_CONFIG_RRLP_USER_PLANE_BIT & aGlonassProtocol) {
      aGlonassProtocol_req.assistedGlonassProtocolMask |=
          QMI_LOC_ASSISTED_GLONASS_PROTOCOL_MASK_RRLP_UP_V02;
  }
  if (GNSS_CONFIG_LLP_USER_PLANE_BIT & aGlonassProtocol) {
      aGlonassProtocol_req.assistedGlonassProtocolMask |=
          QMI_LOC_ASSISTED_GLONASS_PROTOCOL_MASK_LPP_UP_V02;
  }
  if (GNSS_CONFIG_LLP_CONTROL_PLANE_BIT & aGlonassProtocol) {
      aGlonassProtocol_req.assistedGlonassProtocolMask |=
          QMI_LOC_ASSISTED_GLONASS_PROTOCOL_MASK_LPP_CP_V02;
  }

  req_union.pSetProtocolConfigParametersReq = &aGlonassProtocol_req;

  LOC_LOGD("%s:%d]: aGlonassProtocolMask = 0x%x",  __func__, __LINE__,
                             aGlonassProtocol_req.assistedGlonassProtocolMask);

  result = locSyncSendReq(QMI_LOC_SET_PROTOCOL_CONFIG_PARAMETERS_REQ_V02,
                          req_union, LOC_ENGINE_SYNC_REQUEST_LONG_TIMEOUT,
                          QMI_LOC_SET_PROTOCOL_CONFIG_PARAMETERS_IND_V02,
                          &aGlonassProtocol_ind);

  if(result != eLOC_CLIENT_SUCCESS ||
     eQMI_LOC_SUCCESS_V02 != aGlonassProtocol_ind.status)
  {
    LOC_LOGE ("%s:%d]: Error status = %s, ind..status = %s ",
              __func__, __LINE__,
              loc_get_v02_client_status_name(result),
              loc_get_v02_qmi_status_name(aGlonassProtocol_ind.status));
    err = LOCATION_ERROR_GENERAL_FAILURE;
  }

  return err;
}

LocationError
LocApiV02::setLPPeProtocolCpSync(GnssConfigLppeControlPlaneMask lppeCP)
{
  LocationError err = LOCATION_ERROR_SUCCESS;
  locClientStatusEnumType result = eLOC_CLIENT_SUCCESS;
  locClientReqUnionType req_union;
  qmiLocSetProtocolConfigParametersReqMsgT_v02 lppe_req;
  qmiLocSetProtocolConfigParametersIndMsgT_v02 lppe_ind;

  memset(&lppe_req, 0, sizeof(lppe_req));
  memset(&lppe_ind, 0, sizeof(lppe_ind));

  lppe_req.lppeCpConfig_valid = 1;
  if (GNSS_CONFIG_LPPE_CONTROL_PLANE_DBH_BIT & lppeCP) {
      lppe_req.lppeCpConfig |= QMI_LOC_LPPE_MASK_CP_DBH_V02;
  }
  if (GNSS_CONFIG_LPPE_CONTROL_PLANE_WLAN_AP_MEASUREMENTS_BIT & lppeCP) {
      lppe_req.lppeCpConfig |= QMI_LOC_LPPE_MASK_CP_AP_WIFI_MEASUREMENT_V02;
  }
  if (GNSS_CONFIG_LPPE_CONTROL_PLANE_SRN_AP_MEASUREMENTS_BIT & lppeCP) {
      lppe_req.lppeCpConfig |= QMI_LOC_LPPE_MASK_CP_AP_SRN_BTLE_MEASUREMENT_V02;
  }
  if (GNSS_CONFIG_LPPE_CONTROL_PLANE_SENSOR_BARO_MEASUREMENTS_BIT & lppeCP) {
      lppe_req.lppeCpConfig |= QMI_LOC_LPPE_MASK_CP_UBP_V02;
  }

  req_union.pSetProtocolConfigParametersReq = &lppe_req;

  LOC_LOGD("%s:%d]: lppeCpConfig = 0x%" PRIx64,  __func__, __LINE__,
           lppe_req.lppeCpConfig);

  result = locSyncSendReq(QMI_LOC_SET_PROTOCOL_CONFIG_PARAMETERS_REQ_V02,
                          req_union, LOC_ENGINE_SYNC_REQUEST_LONG_TIMEOUT,
                          QMI_LOC_SET_PROTOCOL_CONFIG_PARAMETERS_IND_V02,
                          &lppe_ind);

  if(result != eLOC_CLIENT_SUCCESS ||
     eQMI_LOC_SUCCESS_V02 != lppe_ind.status)
  {
    LOC_LOGE ("%s:%d]: Error status = %s, ind..status = %s ",
              __func__, __LINE__,
              loc_get_v02_client_status_name(result),
              loc_get_v02_qmi_status_name(lppe_ind.status));
    err = LOCATION_ERROR_GENERAL_FAILURE;
  }

  return err;
}

LocationError
LocApiV02::setLPPeProtocolUpSync(GnssConfigLppeUserPlaneMask lppeUP)
{
  LocationError err = LOCATION_ERROR_SUCCESS;
  locClientStatusEnumType result = eLOC_CLIENT_SUCCESS;
  locClientReqUnionType req_union;
  qmiLocSetProtocolConfigParametersReqMsgT_v02 lppe_req;
  qmiLocSetProtocolConfigParametersIndMsgT_v02 lppe_ind;

  memset(&lppe_req, 0, sizeof(lppe_req));
  memset(&lppe_ind, 0, sizeof(lppe_ind));
  memset(&req_union, 0, sizeof(req_union));

  lppe_req.lppeUpConfig_valid = 1;
  if (GNSS_CONFIG_LPPE_USER_PLANE_DBH_BIT & lppeUP) {
      lppe_req.lppeUpConfig |= QMI_LOC_LPPE_MASK_UP_DBH_V02;
  }
  if (GNSS_CONFIG_LPPE_USER_PLANE_WLAN_AP_MEASUREMENTS_BIT & lppeUP) {
      lppe_req.lppeUpConfig |= QMI_LOC_LPPE_MASK_UP_AP_WIFI_MEASUREMENT_V02;
  }
  if (GNSS_CONFIG_LPPE_USER_PLANE_SRN_AP_MEASUREMENTS_BIT & lppeUP) {
      lppe_req.lppeUpConfig |= QMI_LOC_LPPE_MASK_UP_AP_SRN_BTLE_MEASUREMENT_V02;
  }
  if (GNSS_CONFIG_LPPE_USER_PLANE_SENSOR_BARO_MEASUREMENTS_BIT & lppeUP) {
      lppe_req.lppeUpConfig |= QMI_LOC_LPPE_MASK_UP_UBP_V02;
  }

  req_union.pSetProtocolConfigParametersReq = &lppe_req;

  LOC_LOGD("%s:%d]: lppeUpConfig = 0x%" PRIx64,  __func__, __LINE__,
           lppe_req.lppeUpConfig);

  result = locSyncSendReq(QMI_LOC_SET_PROTOCOL_CONFIG_PARAMETERS_REQ_V02,
                          req_union, LOC_ENGINE_SYNC_REQUEST_LONG_TIMEOUT,
                          QMI_LOC_SET_PROTOCOL_CONFIG_PARAMETERS_IND_V02,
                          &lppe_ind);

  if(result != eLOC_CLIENT_SUCCESS ||
     eQMI_LOC_SUCCESS_V02 != lppe_ind.status)
  {
    LOC_LOGE ("%s:%d]: Error status = %s, ind..status = %s ",
              __func__, __LINE__,
              loc_get_v02_client_status_name(result),
              loc_get_v02_qmi_status_name(lppe_ind.status));
    err = LOCATION_ERROR_GENERAL_FAILURE;
  }

  return err;
}

/* Convert event mask from loc eng to loc_api_v02 format */
locClientEventMaskType LocApiV02 :: convertMask(
  LOC_API_ADAPTER_EVENT_MASK_T mask)
{
  locClientEventMaskType eventMask = 0;
  LOC_LOGd("adapter mask = 0x%" PRIx64, mask);

  if (mask & LOC_API_ADAPTER_BIT_PARSED_POSITION_REPORT)
      eventMask |= QMI_LOC_EVENT_MASK_POSITION_REPORT_V02;

  if (mask & LOC_API_ADAPTER_BIT_PARSED_UNPROPAGATED_POSITION_REPORT)
      eventMask |= QMI_LOC_EVENT_MASK_UNPROPAGATED_POSITION_REPORT_V02;

  if (mask & LOC_API_ADAPTER_BIT_SATELLITE_REPORT)
      eventMask |= QMI_LOC_EVENT_MASK_GNSS_SV_INFO_V02;

  /* treat NMEA_1Hz and NMEA_POSITION_REPORT the same*/
  if ((mask & LOC_API_ADAPTER_BIT_NMEA_POSITION_REPORT) ||
      (mask & LOC_API_ADAPTER_BIT_NMEA_1HZ_REPORT) ) {
      eventMask |= QMI_LOC_EVENT_MASK_NMEA_V02;
      // if registering for NMEA event, also register for ENGINE STATE event so that we can
      // register for NMEA event when Engine turns ON and deregister when Engine turns OFF
      eventMask |= QMI_LOC_EVENT_MASK_ENGINE_STATE_V02;
  }

  if (mask & LOC_API_ADAPTER_BIT_NI_NOTIFY_VERIFY_REQUEST)
      eventMask |= QMI_LOC_EVENT_MASK_NI_NOTIFY_VERIFY_REQ_V02;

  if (mask & LOC_API_ADAPTER_BIT_ASSISTANCE_DATA_REQUEST)
  {
    eventMask |= QMI_LOC_EVENT_MASK_INJECT_PREDICTED_ORBITS_REQ_V02;
    eventMask |= QMI_LOC_EVENT_MASK_INJECT_TIME_REQ_V02;
  }

  if (mask & LOC_API_ADAPTER_BIT_POSITION_INJECTION_REQUEST)
      eventMask |= QMI_LOC_EVENT_MASK_INJECT_POSITION_REQ_V02;

  if (mask & LOC_API_ADAPTER_BIT_STATUS_REPORT)
  {
      eventMask |= (QMI_LOC_EVENT_MASK_ENGINE_STATE_V02);
  }

  if (mask & LOC_API_ADAPTER_BIT_LOCATION_SERVER_REQUEST)
      eventMask |= QMI_LOC_EVENT_MASK_LOCATION_SERVER_CONNECTION_REQ_V02;

  if (mask & LOC_API_ADAPTER_BIT_REQUEST_WIFI)
      eventMask |= QMI_LOC_EVENT_MASK_WIFI_REQ_V02;

  if (mask & LOC_API_ADAPTER_BIT_SENSOR_STATUS)
      eventMask |= QMI_LOC_EVENT_MASK_SENSOR_STREAMING_READY_STATUS_V02;

  if (mask & LOC_API_ADAPTER_BIT_REQUEST_TIME_SYNC)
      eventMask |= QMI_LOC_EVENT_MASK_TIME_SYNC_REQ_V02;

  if (mask & LOC_API_ADAPTER_BIT_REPORT_SPI)
      eventMask |= QMI_LOC_EVENT_MASK_SET_SPI_STREAMING_REPORT_V02;

  if (mask & LOC_API_ADAPTER_BIT_REPORT_NI_GEOFENCE)
      eventMask |= QMI_LOC_EVENT_MASK_NI_GEOFENCE_NOTIFICATION_V02;

  if (mask & LOC_API_ADAPTER_BIT_GEOFENCE_GEN_ALERT)
      eventMask |= QMI_LOC_EVENT_MASK_GEOFENCE_GEN_ALERT_V02;

  if (mask & LOC_API_ADAPTER_BIT_REPORT_GENFENCE_BREACH)
      eventMask |= QMI_LOC_EVENT_MASK_GEOFENCE_BREACH_NOTIFICATION_V02;

  if (mask & LOC_API_ADAPTER_BIT_BATCHED_GENFENCE_BREACH_REPORT) {
      if (ContextBase::isMessageSupported(LOC_API_ADAPTER_MESSAGE_BATCHED_GENFENCE_BREACH)) {
          eventMask |= QMI_LOC_EVENT_MASK_GEOFENCE_BATCH_BREACH_NOTIFICATION_V02;
      } else {
          eventMask |= QMI_LOC_EVENT_MASK_GEOFENCE_BREACH_NOTIFICATION_V02;
      }
  }

  if (mask & LOC_API_ADAPTER_BIT_PEDOMETER_CTRL)
      eventMask |= QMI_LOC_EVENT_MASK_PEDOMETER_CONTROL_V02;

  if (mask & LOC_API_ADAPTER_BIT_REPORT_GENFENCE_DWELL)
      eventMask |= QMI_LOC_EVENT_MASK_GEOFENCE_BATCH_DWELL_NOTIFICATION_V02;

  if (mask & LOC_API_ADAPTER_BIT_MOTION_CTRL)
      eventMask |= QMI_LOC_EVENT_MASK_MOTION_DATA_CONTROL_V02;

  if (mask & LOC_API_ADAPTER_BIT_REQUEST_WIFI_AP_DATA)
      eventMask |= QMI_LOC_EVENT_MASK_INJECT_WIFI_AP_DATA_REQ_V02;

  if(mask & LOC_API_ADAPTER_BIT_BATCH_FULL)
      eventMask |= QMI_LOC_EVENT_MASK_BATCH_FULL_NOTIFICATION_V02;

  if(mask & LOC_API_ADAPTER_BIT_BATCH_STATUS)
      eventMask |= QMI_LOC_EVENT_MASK_BATCHING_STATUS_V02;

  if(mask & LOC_API_ADAPTER_BIT_BATCHED_POSITION_REPORT)
      eventMask |= QMI_LOC_EVENT_MASK_LIVE_BATCHED_POSITION_REPORT_V02;

  if(mask & LOC_API_ADAPTER_BIT_GNSS_MEASUREMENT_REPORT)
        eventMask |= QMI_LOC_EVENT_MASK_GNSS_MEASUREMENT_REPORT_V02;

  if(mask & LOC_API_ADAPTER_BIT_GNSS_SV_POLYNOMIAL_REPORT)
      eventMask |= QMI_LOC_EVENT_MASK_GNSS_SV_POLYNOMIAL_REPORT_V02;

  if(mask & LOC_API_ADAPTER_BIT_GNSS_SV_EPHEMERIS_REPORT)
        eventMask |= QMI_LOC_EVENT_MASK_EPHEMERIS_REPORT_V02;

  // for GDT
  if(mask & LOC_API_ADAPTER_BIT_GDT_UPLOAD_BEGIN_REQ)
      eventMask |= QMI_LOC_EVENT_MASK_GDT_UPLOAD_BEGIN_REQ_V02;

  if(mask & LOC_API_ADAPTER_BIT_GDT_UPLOAD_END_REQ)
      eventMask |= QMI_LOC_EVENT_MASK_GDT_UPLOAD_END_REQ_V02;

  if (mask & LOC_API_ADAPTER_BIT_GNSS_MEASUREMENT)
      eventMask |= QMI_LOC_EVENT_MASK_GNSS_MEASUREMENT_REPORT_V02;

  if(mask & LOC_API_ADAPTER_BIT_REQUEST_TIMEZONE)
      eventMask |= QMI_LOC_EVENT_MASK_GET_TIME_ZONE_REQ_V02;

  if(mask & LOC_API_ADAPTER_BIT_REQUEST_SRN_DATA)
      eventMask |= QMI_LOC_EVENT_MASK_INJECT_SRN_AP_DATA_REQ_V02 ;

  if (mask & LOC_API_ADAPTER_BIT_FDCL_SERVICE_REQ)
      eventMask |= QMI_LOC_EVENT_MASK_FDCL_SERVICE_REQ_V02;

  if (mask & LOC_API_ADAPTER_BIT_BS_OBS_DATA_SERVICE_REQ)
      eventMask |= QMI_LOC_EVENT_MASK_BS_OBS_DATA_SERVICE_REQ_V02;

  if (mask & LOC_API_ADAPTER_BIT_LOC_SYSTEM_INFO)
      eventMask |= QMI_LOC_EVENT_MASK_NEXT_LS_INFO_REPORT_V02;

  if (mask & LOC_API_ADAPTER_BIT_EVENT_REPORT_INFO)
      eventMask |= QMI_LOC_EVENT_MASK_GNSS_EVENT_REPORT_V02;

  if (mask & LOC_API_ADAPTER_BIT_GNSS_NHZ_MEASUREMENT) {
      eventMask |= QMI_LOC_EVENT_MASK_GNSS_NHZ_MEASUREMENT_REPORT_V02;
  }

  if (mask & LOC_API_ADAPTER_BIT_LATENCY_INFORMATION) {
      eventMask |= QMI_LOC_EVENT_MASK_LATENCY_INFORMATION_REPORT_V02;
  }

  return eventMask;
}

qmiLocLockEnumT_v02 LocApiV02 ::convertGpsLockFromAPItoQMI(GnssConfigGpsLock lock)
{
    switch (lock)
    {
      case GNSS_CONFIG_GPS_LOCK_MO_AND_NI:
        return eQMI_LOC_LOCK_ALL_V02;
      case GNSS_CONFIG_GPS_LOCK_MO:
        return eQMI_LOC_LOCK_MI_V02;
      case GNSS_CONFIG_GPS_LOCK_NI:
        return eQMI_LOC_LOCK_MT_V02;
      case GNSS_CONFIG_GPS_LOCK_NONE:
      default:
        return eQMI_LOC_LOCK_NONE_V02;
    }
}

GnssConfigGpsLock LocApiV02::convertGpsLockFromQMItoAPI(qmiLocLockEnumT_v02 lock)
{
    switch (lock) {
      case eQMI_LOC_LOCK_MI_V02:
        return GNSS_CONFIG_GPS_LOCK_MO;
      case eQMI_LOC_LOCK_MT_V02:
        return GNSS_CONFIG_GPS_LOCK_NI;
      case eQMI_LOC_LOCK_ALL_V02:
        return GNSS_CONFIG_GPS_LOCK_MO_AND_NI;
      case eQMI_LOC_LOCK_NONE_V02:
      default:
        return GNSS_CONFIG_GPS_LOCK_NONE;
    }
}

/* Convert error from loc_api_v02 to loc eng format*/
enum loc_api_adapter_err LocApiV02 :: convertErr(
  locClientStatusEnumType status)
{
  switch( status)
  {
    case eLOC_CLIENT_SUCCESS:
      return LOC_API_ADAPTER_ERR_SUCCESS;

    case eLOC_CLIENT_FAILURE_GENERAL:
      return LOC_API_ADAPTER_ERR_GENERAL_FAILURE;

    case eLOC_CLIENT_FAILURE_UNSUPPORTED:
      return LOC_API_ADAPTER_ERR_UNSUPPORTED;

    case eLOC_CLIENT_FAILURE_INVALID_PARAMETER:
      return LOC_API_ADAPTER_ERR_INVALID_PARAMETER;

    case eLOC_CLIENT_FAILURE_ENGINE_BUSY:
      return LOC_API_ADAPTER_ERR_ENGINE_BUSY;

    case eLOC_CLIENT_FAILURE_PHONE_OFFLINE:
      return LOC_API_ADAPTER_ERR_PHONE_OFFLINE;

    case eLOC_CLIENT_FAILURE_TIMEOUT:
      return LOC_API_ADAPTER_ERR_TIMEOUT;

    case eLOC_CLIENT_FAILURE_INVALID_HANDLE:
      return LOC_API_ADAPTER_ERR_INVALID_HANDLE;

    case eLOC_CLIENT_FAILURE_SERVICE_NOT_PRESENT:
      return LOC_API_ADAPTER_ERR_SERVICE_NOT_PRESENT;

    case eLOC_CLIENT_FAILURE_INTERNAL:
      return LOC_API_ADAPTER_ERR_INTERNAL;

    default:
      return LOC_API_ADAPTER_ERR_FAILURE;
  }
}

/* convert position report to loc eng format and send the converted
   position to loc eng */

void LocApiV02 :: reportPosition (
  const qmiLocEventPositionReportIndMsgT_v02 *location_report_ptr,
  bool unpropagatedPosition)
{
    UlpLocation location;
    LocPosTechMask tech_Mask = LOC_POS_TECH_MASK_DEFAULT;
    LOC_LOGD("Reporting position from V2 Adapter\n");

    mHlosQtimer2 = getQTimerTickCount();
    LOC_LOGv("mHlosQtimer2=%" PRIi64 " ", mHlosQtimer2);

    memset(&location, 0, sizeof (UlpLocation));
    location.size = sizeof(location);
    location.unpropagatedPosition = unpropagatedPosition;
    GnssDataNotification dataNotify = {};
    int msInWeek = -1;

    GpsLocationExtended locationExtended;
    memset(&locationExtended, 0, sizeof (GpsLocationExtended));
    locationExtended.size = sizeof(locationExtended);

    locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_OUTPUT_ENG_TYPE;
    locationExtended.locOutputEngType = LOC_OUTPUT_ENGINE_SPE;
    locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_OUTPUT_ENG_MASK;
    locationExtended.locOutputEngMask = STANDARD_POSITIONING_ENGINE;

    struct timespec apTimestamp;
    if( clock_gettime( CLOCK_BOOTTIME, &apTimestamp)== 0)
    {
       locationExtended.timeStamp.apTimeStamp.tv_sec = apTimestamp.tv_sec;
       locationExtended.timeStamp.apTimeStamp.tv_nsec = apTimestamp.tv_nsec;
       locationExtended.timeStamp.apTimeStampUncertaintyMs = (float)ap_timestamp_uncertainty;
    }
    else
    {
       locationExtended.timeStamp.apTimeStampUncertaintyMs = FLT_MAX;
       LOC_LOGE("%s:%d Error in clock_gettime() ",__func__, __LINE__);
    }
    LOC_LOGd("QMI_PosPacketTime %" PRIu32 "(sec) %" PRIu32 "(nsec), QMI_spoofReportMask %" PRIu64,
                 locationExtended.timeStamp.apTimeStamp.tv_sec,
                 locationExtended.timeStamp.apTimeStamp.tv_nsec,
                 location_report_ptr->spoofReportMask);

    // Process the position from final and intermediate reports
    memset(&dataNotify, 0, sizeof(dataNotify));
    msInWeek = (int)location_report_ptr->gpsTime.gpsTimeOfWeekMs;

    if (location_report_ptr->jammerIndicatorList_valid) {
        LOC_LOGV("%s:%d jammerIndicator is present len=%d",
                 __func__, __LINE__,
                 location_report_ptr->jammerIndicatorList_len);
        /* msInWeek is used to indicate if jammer indicator is present in this message.
           The appropriate action will be taken in GnssAdapter
           There are three cases as follows:
           1. jammer is not present (old modem image that doesn't support this) then
              msInWeek is set above, has a value >=0 and it is used in GnssAdapter to
              validate when parsing jammer value from NMEA debug message
           2. jammer is present and at least one satellite has a valid value, then
              msInWeek is -1
           3. jammer is present, but the values for all satellites are invalid
              (GNSS_INVALID_JAMMER_IND) then msInWeek is -2 */
        msInWeek = -2;
        for (uint32_t i = 1; i < location_report_ptr->jammerIndicatorList_len; i++) {
            dataNotify.gnssDataMask[i-1] = 0;
            dataNotify.agc[i-1] = 0.0;
            dataNotify.jammerInd[i-1] = 0.0;
            if (GNSS_INVALID_JAMMER_IND !=
                location_report_ptr->jammerIndicatorList[i].agcMetricDb) {
                LOC_LOGv("agcMetricDb[%d]=0x%X",
                         i, location_report_ptr->jammerIndicatorList[i].agcMetricDb);
                dataNotify.gnssDataMask[i-1] |= GNSS_LOC_DATA_AGC_BIT;
                dataNotify.agc[i-1] =
                    (double)location_report_ptr->jammerIndicatorList[i].agcMetricDb / 100.0;
                msInWeek = -1;
            }
            if (GNSS_INVALID_JAMMER_IND !=
                location_report_ptr->jammerIndicatorList[i].bpMetricDb) {
                LOC_LOGv("bpMetricDb[%d]=0x%X",
                         i, location_report_ptr->jammerIndicatorList[i].bpMetricDb);
                dataNotify.gnssDataMask[i-1] |= GNSS_LOC_DATA_JAMMER_IND_BIT;
                dataNotify.jammerInd[i-1] =
                    (double)location_report_ptr->jammerIndicatorList[i].bpMetricDb / 100.0;
                msInWeek = -1;
            }
        }
    } else {
        LOC_LOGd("jammerIndicator is not present");
    }

    if ((false == mIsFirstFinalFixReported) &&
            (eQMI_LOC_SESS_STATUS_SUCCESS_V02 == location_report_ptr->sessionStatus)) {
        loc_boot_kpi_marker("L - LocApiV02 First Final Fix");
        mIsFirstFinalFixReported = true;
    }
    if((location_report_ptr->sessionStatus == eQMI_LOC_SESS_STATUS_SUCCESS_V02) ||
       (location_report_ptr->sessionStatus == eQMI_LOC_SESS_STATUS_IN_PROGRESS_V02)) {
        // Latitude & Longitude
        if ((1 == location_report_ptr->latitude_valid) &&
            (1 == location_report_ptr->longitude_valid))
        {
            location.gpsLocation.flags  |= LOC_GPS_LOCATION_HAS_LAT_LONG;
            location.gpsLocation.latitude  = location_report_ptr->latitude;
            location.gpsLocation.longitude = location_report_ptr->longitude;
        } else {
            LocApiBase::reportData(dataNotify, msInWeek);
        }

        // Time stamp (UTC)
        if (location_report_ptr->timestampUtc_valid == 1)
        {
            location.gpsLocation.timestamp = location_report_ptr->timestampUtc;
        }

        // Altitude
        if (location_report_ptr->altitudeWrtEllipsoid_valid == 1  )
        {
            location.gpsLocation.flags  |= LOC_GPS_LOCATION_HAS_ALTITUDE;
            location.gpsLocation.altitude = location_report_ptr->altitudeWrtEllipsoid;
        }

        // Altitude assumed or calculated info
        if (location_report_ptr->altitudeAssumed_valid == 1) {
            locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_ALTITUDE_ASSUMED;
            locationExtended.altitudeAssumed = location_report_ptr->altitudeAssumed;
        }

        // Speed
        if (location_report_ptr->speedHorizontal_valid == 1)
        {
            location.gpsLocation.flags  |= LOC_GPS_LOCATION_HAS_SPEED;
            location.gpsLocation.speed = location_report_ptr->speedHorizontal;
        }

        // Heading
        if (location_report_ptr->heading_valid == 1)
        {
            location.gpsLocation.flags  |= LOC_GPS_LOCATION_HAS_BEARING;
            location.gpsLocation.bearing = location_report_ptr->heading;
        }

        // Uncertainty (circular)
        if (location_report_ptr->horUncCircular_valid) {
            location.gpsLocation.flags |= LOC_GPS_LOCATION_HAS_ACCURACY;
            location.gpsLocation.accuracy = location_report_ptr->horUncCircular;
        } else if (location_report_ptr->horUncEllipseSemiMinor_valid &&
                   location_report_ptr->horUncEllipseSemiMajor_valid) {
            location.gpsLocation.flags |= LOC_GPS_LOCATION_HAS_ACCURACY;
            location.gpsLocation.accuracy =
                sqrt((location_report_ptr->horUncEllipseSemiMinor *
                      location_report_ptr->horUncEllipseSemiMinor) +
                     (location_report_ptr->horUncEllipseSemiMajor *
                      location_report_ptr->horUncEllipseSemiMajor));
        }

        // If horConfidence_valid is true, and horConfidence value is less than 68%
        // then scale the accuracy value to 68% confidence.
        if (location_report_ptr->horConfidence_valid)
        {
            bool is_CircUnc = (location_report_ptr->horUncCircular_valid) ?
                                                                    true : false;
            scaleAccuracyTo68PercentConfidence(location_report_ptr->horConfidence,
                                               location.gpsLocation,
                                               is_CircUnc);
        }

        // Technology Mask
        tech_Mask |= location_report_ptr->technologyMask;
        locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_POS_TECH_MASK;
        locationExtended.tech_mask = convertPosTechMask(location_report_ptr->technologyMask);

        //Mark the location source as from GNSS
        location.gpsLocation.flags |= LOCATION_HAS_SOURCE_INFO;
        location.position_source = ULP_LOCATION_IS_FROM_GNSS;

        if (location_report_ptr->spoofReportMask_valid)
        {
            location.gpsLocation.flags |= LOC_GPS_LOCATION_HAS_SPOOF_MASK;
            location.gpsLocation.spoof_mask = (uint32_t)location_report_ptr->spoofReportMask;
        }

        if (location_report_ptr->magneticDeviation_valid)
        {
            locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_MAG_DEV;
            locationExtended.magneticDeviation = location_report_ptr->magneticDeviation;
        }

        if (location_report_ptr->conformityIndex_valid) {
            locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_CONFORMITY_INDEX;
            locationExtended.conformityIndex = location_report_ptr->conformityIndex;
        }

        if (location_report_ptr->DOP_valid)
        {
            locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_DOP;
            locationExtended.pdop = location_report_ptr->DOP.PDOP;
            locationExtended.hdop = location_report_ptr->DOP.HDOP;
            locationExtended.vdop = location_report_ptr->DOP.VDOP;
        }

        if (location_report_ptr->altitudeWrtMeanSeaLevel_valid)
        {
            locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_ALTITUDE_MEAN_SEA_LEVEL;
            locationExtended.altitudeMeanSeaLevel = location_report_ptr->altitudeWrtMeanSeaLevel;
        }

        if (location_report_ptr->vertUnc_valid)
        {
           locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_VERT_UNC;
           locationExtended.vert_unc = location_report_ptr->vertUnc;
        }

        if (location_report_ptr->speedUnc_valid)
        {
           locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_SPEED_UNC;
           locationExtended.speed_unc = location_report_ptr->speedUnc;
        }
        if (location_report_ptr->headingUnc_valid)
        {
           locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_BEARING_UNC;
           locationExtended.bearing_unc = location_report_ptr->headingUnc;
        }
        if (location_report_ptr->horReliability_valid)
        {
           locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_HOR_RELIABILITY;
           switch (location_report_ptr->horReliability)
           {
              case eQMI_LOC_RELIABILITY_NOT_SET_V02 :
                locationExtended.horizontal_reliability = LOC_RELIABILITY_NOT_SET;
                break;
              case eQMI_LOC_RELIABILITY_VERY_LOW_V02 :
                locationExtended.horizontal_reliability = LOC_RELIABILITY_VERY_LOW;
                break;
              case eQMI_LOC_RELIABILITY_LOW_V02 :
                locationExtended.horizontal_reliability = LOC_RELIABILITY_LOW;
                break;
              case eQMI_LOC_RELIABILITY_MEDIUM_V02 :
                locationExtended.horizontal_reliability = LOC_RELIABILITY_MEDIUM;
                break;
              case eQMI_LOC_RELIABILITY_HIGH_V02 :
                locationExtended.horizontal_reliability = LOC_RELIABILITY_HIGH;
                break;
              default:
                locationExtended.horizontal_reliability = LOC_RELIABILITY_NOT_SET;
                break;
           }
        }
        if (location_report_ptr->vertReliability_valid)
        {
           locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_VERT_RELIABILITY;
           switch (location_report_ptr->vertReliability)
           {
              case eQMI_LOC_RELIABILITY_NOT_SET_V02 :
                locationExtended.vertical_reliability = LOC_RELIABILITY_NOT_SET;
                break;
              case eQMI_LOC_RELIABILITY_VERY_LOW_V02 :
                locationExtended.vertical_reliability = LOC_RELIABILITY_VERY_LOW;
                break;
              case eQMI_LOC_RELIABILITY_LOW_V02 :
                locationExtended.vertical_reliability = LOC_RELIABILITY_LOW;
                break;
              case eQMI_LOC_RELIABILITY_MEDIUM_V02 :
                locationExtended.vertical_reliability = LOC_RELIABILITY_MEDIUM;
                break;
              case eQMI_LOC_RELIABILITY_HIGH_V02 :
                locationExtended.vertical_reliability = LOC_RELIABILITY_HIGH;
                break;
              default:
                locationExtended.vertical_reliability = LOC_RELIABILITY_NOT_SET;
                break;
           }
        }

        if (location_report_ptr->horUncEllipseSemiMajor_valid)
        {
            locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_HOR_ELIP_UNC_MAJOR;
            locationExtended.horUncEllipseSemiMajor = location_report_ptr->horUncEllipseSemiMajor;
        }
        if (location_report_ptr->horUncEllipseSemiMinor_valid)
        {
            locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_HOR_ELIP_UNC_MINOR;
            locationExtended.horUncEllipseSemiMinor = location_report_ptr->horUncEllipseSemiMinor;
        }
        if (location_report_ptr->horUncEllipseOrientAzimuth_valid)
        {
            locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_HOR_ELIP_UNC_AZIMUTH;
            locationExtended.horUncEllipseOrientAzimuth =
                location_report_ptr->horUncEllipseOrientAzimuth;
        }

        // If the horizontal uncertainty ellipse info is available,
        // calculate the horizontal uncertainty along north and east
        if (location_report_ptr->horUncEllipseSemiMajor_valid &&
            location_report_ptr->horUncEllipseSemiMinor_valid &&
            location_report_ptr->horUncEllipseOrientAzimuth_valid)
        {
            double cosVal = cos((double)locationExtended.horUncEllipseOrientAzimuth);
            double sinVal = sin((double)locationExtended.horUncEllipseOrientAzimuth);
            double major = locationExtended.horUncEllipseSemiMajor;
            double minor = locationExtended.horUncEllipseSemiMinor;

            double northSquare = major*major * cosVal*cosVal + minor*minor * sinVal*sinVal;
            double eastSquare =  major*major * sinVal*sinVal + minor*minor * cosVal*cosVal;

            locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_NORTH_STD_DEV;
            locationExtended.northStdDeviation = sqrt(northSquare);

            locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_EAST_STD_DEV;
            locationExtended.eastStdDeviation  = sqrt(eastSquare);
        }

        if (((location_report_ptr->expandedGnssSvUsedList_valid) &&
                (location_report_ptr->expandedGnssSvUsedList_len != 0)) ||
                ((location_report_ptr->gnssSvUsedList_valid) &&
                (location_report_ptr->gnssSvUsedList_len != 0)))
        {
            uint32_t idx=0;
            uint32_t gnssSvUsedList_len = 0;
            uint16_t gnssSvIdUsed = 0;
            const uint16_t *svUsedList;
            bool multiBandTypesAvailable = false;

            if (location_report_ptr->expandedGnssSvUsedList_valid)
            {
                gnssSvUsedList_len = location_report_ptr->expandedGnssSvUsedList_len;
                svUsedList = location_report_ptr->expandedGnssSvUsedList;
            } else if (location_report_ptr->gnssSvUsedList_valid)
            {
                gnssSvUsedList_len = location_report_ptr->gnssSvUsedList_len;
                svUsedList = location_report_ptr->gnssSvUsedList;
            }

            // If multifreq data is not available then default to L1 for all constellations.
            if ((location_report_ptr->gnssSvUsedSignalTypeList_valid) &&
                    (location_report_ptr->gnssSvUsedSignalTypeList_len != 0)) {
                multiBandTypesAvailable = true;
            }

            LOC_LOGv("sv length %d ", gnssSvUsedList_len);

            locationExtended.numOfMeasReceived = gnssSvUsedList_len;
            memset(locationExtended.measUsageInfo, 0, sizeof(locationExtended.measUsageInfo));
            // Set of used_in_fix SV ID
            bool reported = LocApiBase::needReport(location,
                                                   (eQMI_LOC_SESS_STATUS_IN_PROGRESS_V02 ==
                                                   location_report_ptr->sessionStatus ?
                                                   LOC_SESS_INTERMEDIATE : LOC_SESS_SUCCESS),
                                                   tech_Mask);
            if (unpropagatedPosition || reported) {
                for (idx = 0; idx < gnssSvUsedList_len; idx++)
                {
                    gnssSvIdUsed = svUsedList[idx];
                    locationExtended.measUsageInfo[idx].gnssSvId = gnssSvIdUsed;
                    locationExtended.measUsageInfo[idx].carrierPhaseAmbiguityType =
                            CARRIER_PHASE_AMBIGUITY_RESOLUTION_NONE;

                    qmiLocGnssSignalTypeMaskT_v02 qmiGnssSignalType =
                            location_report_ptr->gnssSvUsedSignalTypeList[idx];
                    GnssSignalTypeMask gnssSignalTypeMask =
                            convertQmiGnssSignalType(qmiGnssSignalType);
                    LOC_LOGd("sv id %d, qmi signal type: 0x%" PRIx64 ", hal signal type: 0x%x",
                             gnssSvIdUsed, qmiGnssSignalType, gnssSignalTypeMask);

                    if (gnssSvIdUsed <= GPS_SV_PRN_MAX)
                    {
                        uint64_t bit = (1ULL << (gnssSvIdUsed - GPS_SV_PRN_MIN));
                        locationExtended.gnss_sv_used_ids.gps_sv_used_ids_mask |= bit;
                        locationExtended.measUsageInfo[idx].gnssConstellation =
                                GNSS_LOC_SV_SYSTEM_GPS;
                        if (multiBandTypesAvailable) {
                            locationExtended.measUsageInfo[idx].gnssSignalType =
                                    gnssSignalTypeMask;
                            if (locationExtended.measUsageInfo[idx].gnssSignalType &
                                    GNSS_SIGNAL_GPS_L1CA) {
                                locationExtended.gnss_mb_sv_used_ids.gps_l1ca_sv_used_ids_mask
                                        |= bit;
                            }
                            if (locationExtended.measUsageInfo[idx].gnssSignalType &
                                    GNSS_SIGNAL_GPS_L1C) {
                                locationExtended.gnss_mb_sv_used_ids.gps_l1c_sv_used_ids_mask
                                        |= bit;
                            }
                            if (locationExtended.measUsageInfo[idx].gnssSignalType &
                                    GNSS_SIGNAL_GPS_L2) {
                                locationExtended.gnss_mb_sv_used_ids.gps_l2_sv_used_ids_mask
                                        |= bit;
                            }
                            if (locationExtended.measUsageInfo[idx].gnssSignalType &
                                    GNSS_SIGNAL_GPS_L5) {
                                locationExtended.gnss_mb_sv_used_ids.gps_l5_sv_used_ids_mask
                                        |= bit;
                            }
                        } else {
                            locationExtended.measUsageInfo[idx].gnssSignalType =
                                    GNSS_SIGNAL_GPS_L1CA;
                        }
                    }
                    else if ((gnssSvIdUsed >= GLO_SV_PRN_MIN) &&
                             (gnssSvIdUsed <= GLO_SV_PRN_MAX))
                    {
                        uint64_t bit = (1ULL << (gnssSvIdUsed - GLO_SV_PRN_MIN));
                        locationExtended.gnss_sv_used_ids.glo_sv_used_ids_mask |= bit;
                        locationExtended.measUsageInfo[idx].gnssConstellation =
                                GNSS_LOC_SV_SYSTEM_GLONASS;
                        if (multiBandTypesAvailable) {
                            locationExtended.measUsageInfo[idx].gnssSignalType =
                                    gnssSignalTypeMask;

                            if (locationExtended.measUsageInfo[idx].gnssSignalType &
                                    GNSS_SIGNAL_GLONASS_G1) {
                                locationExtended.gnss_mb_sv_used_ids.glo_g1_sv_used_ids_mask
                                        |= bit;
                            }
                            if (locationExtended.measUsageInfo[idx].gnssSignalType &
                                    GNSS_SIGNAL_GLONASS_G2) {
                                locationExtended.gnss_mb_sv_used_ids.glo_g2_sv_used_ids_mask
                                        |= bit;
                            }
                        } else {
                            locationExtended.measUsageInfo[idx].gnssSignalType =
                                    GNSS_SIGNAL_GLONASS_G1;
                        }

                    }
                    else if ((gnssSvIdUsed >= BDS_SV_PRN_MIN) &&
                             (gnssSvIdUsed <= BDS_SV_PRN_MAX))
                    {
                        uint64_t bit = (1ULL << (gnssSvIdUsed - BDS_SV_PRN_MIN));
                        locationExtended.gnss_sv_used_ids.bds_sv_used_ids_mask |= bit;
                        locationExtended.measUsageInfo[idx].gnssConstellation =
                                GNSS_LOC_SV_SYSTEM_BDS;
                        if (multiBandTypesAvailable) {
                            locationExtended.measUsageInfo[idx].gnssSignalType =
                                    gnssSignalTypeMask;
                            if (locationExtended.measUsageInfo[idx].gnssSignalType &
                                    GNSS_SIGNAL_BEIDOU_B1I) {
                                locationExtended.gnss_mb_sv_used_ids.bds_b1i_sv_used_ids_mask
                                        |= bit;
                            }
                            if (locationExtended.measUsageInfo[idx].gnssSignalType &
                                    GNSS_SIGNAL_BEIDOU_B1C) {
                                locationExtended.gnss_mb_sv_used_ids.bds_b1c_sv_used_ids_mask
                                        |= bit;
                            }
                            if (locationExtended.measUsageInfo[idx].gnssSignalType &
                                    GNSS_SIGNAL_BEIDOU_B2I) {
                                locationExtended.gnss_mb_sv_used_ids.bds_b2i_sv_used_ids_mask
                                        |= bit;
                            }
                            if (locationExtended.measUsageInfo[idx].gnssSignalType &
                                    GNSS_SIGNAL_BEIDOU_B2AI) {
                                locationExtended.gnss_mb_sv_used_ids.bds_b2ai_sv_used_ids_mask
                                        |= bit;
                            }
                            if (locationExtended.measUsageInfo[idx].gnssSignalType &
                                    GNSS_SIGNAL_BEIDOU_B2AQ) {
                                locationExtended.gnss_mb_sv_used_ids.bds_b2aq_sv_used_ids_mask
                                        |= bit;
                            }
                        } else {
                            locationExtended.measUsageInfo[idx].gnssSignalType =
                                    GNSS_SIGNAL_BEIDOU_B1I;
                        }
                    }
                    else if ((gnssSvIdUsed >= GAL_SV_PRN_MIN) &&
                             (gnssSvIdUsed <= GAL_SV_PRN_MAX))
                    {
                        uint64_t bit = (1ULL << (gnssSvIdUsed - GAL_SV_PRN_MIN));
                        locationExtended.gnss_sv_used_ids.gal_sv_used_ids_mask |= bit;
                        locationExtended.measUsageInfo[idx].gnssConstellation =
                                GNSS_LOC_SV_SYSTEM_GALILEO;
                        if (multiBandTypesAvailable) {
                            locationExtended.measUsageInfo[idx].gnssSignalType =
                                    gnssSignalTypeMask;

                            if (locationExtended.measUsageInfo[idx].gnssSignalType &
                                    GNSS_SIGNAL_GALILEO_E1) {
                                locationExtended.gnss_mb_sv_used_ids.gal_e1_sv_used_ids_mask
                                        |= bit;
                            }
                            if (locationExtended.measUsageInfo[idx].gnssSignalType &
                                    GNSS_SIGNAL_GALILEO_E5A) {
                                locationExtended.gnss_mb_sv_used_ids.gal_e5a_sv_used_ids_mask
                                        |= bit;
                            }
                            if (locationExtended.measUsageInfo[idx].gnssSignalType &
                                    GNSS_SIGNAL_GALILEO_E5B) {
                                locationExtended.gnss_mb_sv_used_ids.gal_e5b_sv_used_ids_mask
                                        |= bit;
                            }
                        } else {
                            locationExtended.measUsageInfo[idx].gnssSignalType =
                                    GNSS_SIGNAL_GALILEO_E1;
                        }
                    }
                    else if ((gnssSvIdUsed >= QZSS_SV_PRN_MIN) &&
                             (gnssSvIdUsed <= QZSS_SV_PRN_MAX))
                    {
                        uint64_t bit = (1ULL << (gnssSvIdUsed - QZSS_SV_PRN_MIN));
                        locationExtended.gnss_sv_used_ids.qzss_sv_used_ids_mask |= bit;
                        locationExtended.measUsageInfo[idx].gnssConstellation =
                                GNSS_LOC_SV_SYSTEM_QZSS;
                        if (multiBandTypesAvailable) {
                            locationExtended.measUsageInfo[idx].gnssSignalType =
                                    gnssSignalTypeMask;

                            if (locationExtended.measUsageInfo[idx].gnssSignalType &
                                    GNSS_SIGNAL_QZSS_L1CA) {
                                locationExtended.gnss_mb_sv_used_ids.qzss_l1ca_sv_used_ids_mask
                                        |= bit;
                            }
                            if (locationExtended.measUsageInfo[idx].gnssSignalType &
                                    GNSS_SIGNAL_QZSS_L1S) {
                                locationExtended.gnss_mb_sv_used_ids.qzss_l1s_sv_used_ids_mask
                                        |= bit;
                            }
                            if (locationExtended.measUsageInfo[idx].gnssSignalType &
                                    GNSS_SIGNAL_QZSS_L2) {
                                locationExtended.gnss_mb_sv_used_ids.qzss_l2_sv_used_ids_mask
                                        |= bit;
                            }
                            if (locationExtended.measUsageInfo[idx].gnssSignalType &
                                    GNSS_SIGNAL_QZSS_L5) {
                                locationExtended.gnss_mb_sv_used_ids.qzss_l5_sv_used_ids_mask
                                        |= bit;
                            }
                        } else {
                                locationExtended.measUsageInfo[idx].gnssSignalType =
                                        GNSS_SIGNAL_QZSS_L1CA;
                        }
                    }
                    else if ((gnssSvIdUsed >= NAVIC_SV_PRN_MIN) &&
                             (gnssSvIdUsed <= NAVIC_SV_PRN_MAX))
                    {
                        locationExtended.gnss_sv_used_ids.navic_sv_used_ids_mask |=
                                (1ULL << (gnssSvIdUsed - NAVIC_SV_PRN_MIN));
                        locationExtended.measUsageInfo[idx].gnssConstellation =
                                GNSS_LOC_SV_SYSTEM_NAVIC;
                        locationExtended.measUsageInfo[idx].gnssSignalType =
                                (multiBandTypesAvailable ?
                                location_report_ptr->gnssSvUsedSignalTypeList[idx] :
                                GNSS_SIGNAL_NAVIC_L5);
                    }
                }
                locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_GNSS_SV_USED_DATA;
                if (multiBandTypesAvailable) {
                    locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_MULTIBAND;
                }
            }
        }

        if (location_report_ptr->navSolutionMask_valid)
        {
            locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_NAV_SOLUTION_MASK;
            locationExtended.navSolutionMask =
                convertNavSolutionMask(location_report_ptr->navSolutionMask);
        }

        if (location_report_ptr->gpsTime_valid)
        {
            locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_GPS_TIME;
            locationExtended.gpsTime.gpsWeek = location_report_ptr->gpsTime.gpsWeek;
            locationExtended.gpsTime.gpsTimeOfWeekMs = location_report_ptr->gpsTime.gpsTimeOfWeekMs;
        }

        if (location_report_ptr->extDOP_valid)
        {
            locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_EXT_DOP;
            locationExtended.extDOP.PDOP = location_report_ptr->extDOP.PDOP;
            locationExtended.extDOP.HDOP = location_report_ptr->extDOP.HDOP;
            locationExtended.extDOP.VDOP = location_report_ptr->extDOP.VDOP;
            locationExtended.extDOP.GDOP = location_report_ptr->extDOP.GDOP;
            locationExtended.extDOP.TDOP = location_report_ptr->extDOP.TDOP;
        }

        if (location_report_ptr->velEnu_valid)
        {
            locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_EAST_VEL;
            locationExtended.eastVelocity = location_report_ptr->velEnu[0];
            locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_NORTH_VEL;
            locationExtended.northVelocity = location_report_ptr->velEnu[1];
            locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_UP_VEL;
            locationExtended.upVelocity = location_report_ptr->velEnu[2];
        }

        if (location_report_ptr->velUncEnu_valid)
        {
            locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_EAST_VEL_UNC;
            locationExtended.eastVelocityStdDeviation = location_report_ptr->velUncEnu[0];
            locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_NORTH_VEL_UNC;
            locationExtended.northVelocityStdDeviation = location_report_ptr->velUncEnu[1];
            locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_UP_VEL_UNC;
            locationExtended.upVelocityStdDeviation = location_report_ptr->velUncEnu[2];
        }
        // fill in GnssSystemTime based on gps timestamp and time uncertainty
        locationExtended.gnssSystemTime.gnssSystemTimeSrc = (Gnss_LocSvSystemEnumType)0;
        if (location_report_ptr->gpsTime_valid)
        {
            locationExtended.gnssSystemTime.gnssSystemTimeSrc = GNSS_LOC_SV_SYSTEM_GPS;
            locationExtended.gnssSystemTime.u.gpsSystemTime.validityMask = 0x0;

            locationExtended.gnssSystemTime.u.gpsSystemTime.systemWeek =
                    locationExtended.gpsTime.gpsWeek;
            locationExtended.gnssSystemTime.u.gpsSystemTime.validityMask |=
                    GNSS_SYSTEM_TIME_WEEK_VALID;

            locationExtended.gnssSystemTime.u.gpsSystemTime.systemMsec =
                    locationExtended.gpsTime.gpsTimeOfWeekMs;
            locationExtended.gnssSystemTime.u.gpsSystemTime.validityMask |=
                    GNSS_SYSTEM_TIME_WEEK_MS_VALID;

            if (location_report_ptr->systemClkTimeBias_valid) {
                locationExtended.gnssSystemTime.u.gpsSystemTime.systemClkTimeBias =
                        location_report_ptr->systemClkTimeBias;
                locationExtended.gnssSystemTime.u.gpsSystemTime.validityMask |=
                        GNSS_SYSTEM_CLK_TIME_BIAS_VALID;
            } else {
                locationExtended.gnssSystemTime.u.gpsSystemTime.systemClkTimeBias = 0.0f;
                locationExtended.gnssSystemTime.u.gpsSystemTime.validityMask |=
                        GNSS_SYSTEM_CLK_TIME_BIAS_VALID;
            }

            if (location_report_ptr->systemClkTimeBiasUnc_valid) {
                locationExtended.gnssSystemTime.u.gpsSystemTime.systemClkTimeUncMs =
                        location_report_ptr->systemClkTimeBiasUnc;
                locationExtended.gnssSystemTime.u.gpsSystemTime.validityMask |=
                        GNSS_SYSTEM_CLK_TIME_BIAS_UNC_VALID;
            } else if (location_report_ptr->timeUnc_valid) {
                locationExtended.gnssSystemTime.u.gpsSystemTime.systemClkTimeUncMs =
                        location_report_ptr->timeUnc;
                locationExtended.gnssSystemTime.u.gpsSystemTime.validityMask |=
                        GNSS_SYSTEM_CLK_TIME_BIAS_UNC_VALID;
            }
        }

        if (location_report_ptr->timeUnc_valid)
        {
            locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_TIME_UNC;
            locationExtended.timeUncMs = location_report_ptr->timeUnc;
        }

        if (location_report_ptr->leapSeconds_valid)
        {
            locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_LEAP_SECONDS;
            locationExtended.leapSeconds = location_report_ptr->leapSeconds;
        }

        if (location_report_ptr->dgnssCorrectionSource_valid) {
            locationExtended.flags |=
                    GPS_LOCATION_EXTENDED_HAS_DGNSS_CORRECTION_SOURCE_TYPE;
            locationExtended.dgnssCorrectionSourceType = (LocDgnssCorrectionSourceType)
                    location_report_ptr->dgnssCorrectionSource;
        }

        if (location_report_ptr->dgnssCorrectionSourceID_valid) {
            locationExtended.flags |=
                    GPS_LOCATION_EXTENDED_HAS_DGNSS_CORRECTION_SOURCE_ID;
            locationExtended.dgnssCorrectionSourceID =
                    location_report_ptr->dgnssCorrectionSourceID;
        }

        if (location_report_ptr->dgnssConstellationUsage_valid) {
            locationExtended.flags |=
                    GPS_LOCATION_EXTENDED_HAS_DGNSS_CONSTELLATION_USAGE;
            convertGnssConestellationMask(location_report_ptr->dgnssConstellationUsage,
                                          locationExtended.dgnssConstellationUsage);
        }

        if (location_report_ptr->dgnssRefStationId_valid) {
            locationExtended.flags |=
                    GPS_LOCATION_EXTENDED_HAS_DGNSS_REF_STATION_ID;
            locationExtended.dgnssRefStationId =
                    location_report_ptr->dgnssRefStationId;
        }

        if (location_report_ptr->dgnssDataAgeMsec_valid) {
            locationExtended.flags |=
                    GPS_LOCATION_EXTENDED_HAS_DGNSS_DATA_AGE;
            locationExtended.dgnssDataAgeMsec =
                    location_report_ptr->dgnssDataAgeMsec;
        }

        int64_t elapsedRealTime = -1;
        int64_t unc = -1;
        if (location_report_ptr->systemTick_valid &&
            location_report_ptr->systemTickUnc_valid) {
            LOC_LOGD("Report position to the upper layer");
            /* deal with Qtimer for ElapsedRealTimeNanos */
            elapsedRealTime = ElapsedRealtimeEstimator::getElapsedRealtimeQtimer(
                    location_report_ptr->systemTick);

            /* Uncertainty on HLOS time is 0, so the uncertainty of the difference
               is the uncertainty of the Qtimer in the modem
               Note that location_report_ptr->systemTickUnc is in msec */
            unc = (int64_t)location_report_ptr->systemTickUnc * 1000000;
        } else if (location_report_ptr->timestampUtc_valid == 1) {
            //If Qtimer isn't valid, estimate the elapsedRealTime
            int64_t locationTimeNanos = (int64_t)(location_report_ptr->timestampUtc) * 1000000;
            bool isCurDataTimeTrustable =
                    (locationTimeNanos % ((int64_t)mMinInterval * 1000000) == 0);
            elapsedRealTime = mPositionElapsedRealTimeCal.
                    getElapsedRealtimeEstimateNanos(locationTimeNanos, isCurDataTimeTrustable,
                                                    (int64_t)mMinInterval * 1000000);
            unc = mPositionElapsedRealTimeCal.getElapsedRealtimeUncNanos();
        }

        if (elapsedRealTime != -1) {
            location.gpsLocation.flags |= LOC_GPS_LOCATION_HAS_ELAPSED_REAL_TIME;
            location.gpsLocation.elapsedRealTime = elapsedRealTime;
            location.gpsLocation.elapsedRealTimeUnc = unc;
        }

        LOC_LOGd("Position elapsedRealtime: %" PRIi64 " uncertainty: %" PRIi64 "",
               location.gpsLocation.elapsedRealTime,
               location.gpsLocation.elapsedRealTimeUnc);

        LOC_LOGv("report position mask: 0x%" PRIx64 ", dgnss info: 0x%x %d %d %d %d,",
                 locationExtended.flags,
                 locationExtended.dgnssConstellationUsage,
                 locationExtended.dgnssCorrectionSourceType,
                 locationExtended.dgnssCorrectionSourceID,
                 locationExtended.dgnssDataAgeMsec,
                 locationExtended.dgnssRefStationId);
        LocApiBase::reportPosition(location,
                                   locationExtended,
                                   (location_report_ptr->sessionStatus ==
                                    eQMI_LOC_SESS_STATUS_IN_PROGRESS_V02 ?
                                    LOC_SESS_INTERMEDIATE : LOC_SESS_SUCCESS),
                                   tech_Mask, &dataNotify, msInWeek);
    }
    else
    {
        LocApiBase::reportPosition(location,
                                   locationExtended,
                                   LOC_SESS_FAILURE,
                                   LOC_POS_TECH_MASK_DEFAULT,
                                   &dataNotify, msInWeek);

        LOC_LOGD("%s:%d]: Ignoring position report with sess status = %d, "
                      "fix id = %u\n", __func__, __LINE__,
                      location_report_ptr->sessionStatus,
                      location_report_ptr->fixId );
    }
}

/*convert signal type to carrier frequency*/
float LocApiV02::convertSignalTypeToCarrierFrequency(
    qmiLocGnssSignalTypeMaskT_v02 signalType,
    uint8_t gloFrequency)
{
    float carrierFrequency = 0.0;

    LOC_LOGv("signalType = 0x%" PRIx64 , signalType);
    switch (signalType) {
    case QMI_LOC_MASK_GNSS_SIGNAL_TYPE_GPS_L1CA_V02:
        carrierFrequency = GPS_L1CA_CARRIER_FREQUENCY;
        break;

    case QMI_LOC_MASK_GNSS_SIGNAL_TYPE_GPS_L1C_V02:
        carrierFrequency = GPS_L1C_CARRIER_FREQUENCY;
        break;

    case QMI_LOC_MASK_GNSS_SIGNAL_TYPE_GPS_L2C_L_V02:
        carrierFrequency = GPS_L2C_L_CARRIER_FREQUENCY;
        break;

    case QMI_LOC_MASK_GNSS_SIGNAL_TYPE_GPS_L5_Q_V02:
        carrierFrequency = GPS_L5_Q_CARRIER_FREQUENCY;
        break;

    case QMI_LOC_MASK_GNSS_SIGNAL_TYPE_GLONASS_G1_V02:
        carrierFrequency = GLONASS_G1_CARRIER_FREQUENCY;
        if ((gloFrequency >= 1 && gloFrequency <= 14)) {
            carrierFrequency += ((gloFrequency - 8) * 562500);
        }
        LOC_LOGv("GLO carFreq after conversion = %f", carrierFrequency);
        break;

    case QMI_LOC_MASK_GNSS_SIGNAL_TYPE_GLONASS_G2_V02:
        carrierFrequency = GLONASS_G2_CARRIER_FREQUENCY;
        if ((gloFrequency >= 1 && gloFrequency <= 14)) {
            carrierFrequency += ((gloFrequency - 8) * 437500);
        }
        LOC_LOGv("GLO carFreq after conversion = %f", carrierFrequency);
        break;

    case QMI_LOC_MASK_GNSS_SIGNAL_TYPE_GALILEO_E1_C_V02:
        carrierFrequency = GALILEO_E1_C_CARRIER_FREQUENCY;
        break;

    case QMI_LOC_MASK_GNSS_SIGNAL_TYPE_GALILEO_E5A_Q_V02:
        carrierFrequency = GALILEO_E5A_Q_CARRIER_FREQUENCY;
        break;

    case QMI_LOC_MASK_GNSS_SIGNAL_TYPE_GALILEO_E5B_Q_V02:
        carrierFrequency = GALILEO_E5B_Q_CARRIER_FREQUENCY;
        break;

    case QMI_LOC_MASK_GNSS_SIGNAL_TYPE_BEIDOU_B1_I_V02:
        carrierFrequency = BEIDOU_B1_I_CARRIER_FREQUENCY;
        break;

    case QMI_LOC_MASK_GNSS_SIGNAL_TYPE_BEIDOU_B1C_V02:
        carrierFrequency = BEIDOU_B1C_CARRIER_FREQUENCY;
        break;

    case QMI_LOC_MASK_GNSS_SIGNAL_TYPE_BEIDOU_B2_I_V02:
        carrierFrequency = BEIDOU_B2_I_CARRIER_FREQUENCY;
        break;

    case QMI_LOC_MASK_GNSS_SIGNAL_TYPE_BEIDOU_B2A_I_V02:
        carrierFrequency = BEIDOU_B2A_I_CARRIER_FREQUENCY;
        break;

    case QMI_LOC_MASK_GNSS_SIGNAL_TYPE_QZSS_L1CA_V02:
        carrierFrequency = QZSS_L1CA_CARRIER_FREQUENCY;
        break;

    case QMI_LOC_MASK_GNSS_SIGNAL_TYPE_QZSS_L1S_V02:
        carrierFrequency = QZSS_L1S_CARRIER_FREQUENCY;
        break;

    case QMI_LOC_MASK_GNSS_SIGNAL_TYPE_QZSS_L2C_L_V02:
        carrierFrequency = QZSS_L2C_L_CARRIER_FREQUENCY;
        break;

    case QMI_LOC_MASK_GNSS_SIGNAL_TYPE_QZSS_L5_Q_V02:
        carrierFrequency = QZSS_L5_Q_CARRIER_FREQUENCY;
        break;

    case QMI_LOC_MASK_GNSS_SIGNAL_TYPE_SBAS_L1_CA_V02:
        carrierFrequency = SBAS_L1_CA_CARRIER_FREQUENCY;
        break;

    case QMI_LOC_MASK_GNSS_SIGNAL_TYPE_BEIDOU_B2A_Q_V02:
        carrierFrequency = BEIDOU_B2A_Q_CARRIER_FREQUENCY;
        break;

    case QMI_LOC_MASK_GNSS_SIGNAL_TYPE_NAVIC_L5_V02:
        carrierFrequency = NAVIC_L5_CARRIER_FREQUENCY;
        break;

    default:
        break;
    }
    return carrierFrequency;
}

static GnssSignalTypeMask getDefaultGnssSignalTypeMask(qmiLocSvSystemEnumT_v02 qmiSvSystemType)
{
    GnssSignalTypeMask gnssSignalType = 0;

    switch (qmiSvSystemType) {
    case eQMI_LOC_SV_SYSTEM_GPS_V02:
        gnssSignalType = GNSS_SIGNAL_GPS_L1CA;
        break;
    case eQMI_LOC_SV_SYSTEM_GALILEO_V02:
        gnssSignalType = GNSS_SIGNAL_GALILEO_E1;
        break;
    case eQMI_LOC_SV_SYSTEM_SBAS_V02:
        gnssSignalType = GNSS_SIGNAL_SBAS_L1;
        break;
    case eQMI_LOC_SV_SYSTEM_GLONASS_V02:
        gnssSignalType = GNSS_SIGNAL_GLONASS_G1;
        break;
    case eQMI_LOC_SV_SYSTEM_BDS_V02:
    case eQMI_LOC_SV_SYSTEM_COMPASS_V02:
        gnssSignalType = GNSS_SIGNAL_BEIDOU_B1I;
        break;
    case eQMI_LOC_SV_SYSTEM_QZSS_V02:
        gnssSignalType = GNSS_SIGNAL_QZSS_L1CA;
        break;
    default:
        break;
    }

    return gnssSignalType;
}

/* convert satellite report to location api format and send the converted
   report to base */
void  LocApiV02 :: reportSv (
    const qmiLocEventGnssSvInfoIndMsgT_v02 *gnss_report_ptr)
{
    GnssSvNotification SvNotify = {};
    int              num_svs_max, i;
    const qmiLocSvInfoStructT_v02 *sv_info_ptr;
    uint8_t gloFrequency = 0;

    num_svs_max = 0;
    if (1 == gnss_report_ptr->expandedSvList_valid) {
        num_svs_max = std::min((uint32_t)QMI_LOC_EXPANDED_SV_INFO_LIST_MAX_SIZE_V02,
                                gnss_report_ptr->expandedSvList_len);
    }
    else if (1 == gnss_report_ptr->svList_valid) {
        num_svs_max = std::min((uint32_t)QMI_LOC_MAX_SV_USED_LIST_LENGTH_V02,
                                gnss_report_ptr->svList_len);
    }
    num_svs_max = std::min(num_svs_max, GNSS_SV_MAX);

    SvNotify.size = sizeof(GnssSvNotification);
    if (gnss_report_ptr->gnssSignalTypeList_valid) {
        SvNotify.gnssSignalTypeMaskValid = true;
    }

    if (1 == gnss_report_ptr->svList_valid ||
        1 == gnss_report_ptr->expandedSvList_valid) {
        SvNotify.count = 0;
        if (0 == gnss_report_ptr->expandedSvList_valid ||
            0 == gnss_report_ptr->rfLoss_valid) {
            /*  For modems that don's send rfLoss in the QMI LOC message
                we need to read this info from gps.conf, this is done
                in the constructor */
            for (int i = RF_LOSS_GPS_CONF; i < RF_LOSS_MAX_CONF; i++) {
                if (0 == rfLossNV[i]) {
                    LOC_LOGw("At least one RF_LOSS is 0 in gps.conf, please configure it");
                    break;
                }
            }
        }
        for(i = 0; i < num_svs_max; i++) {
            if (1 == gnss_report_ptr->expandedSvList_valid) {
                sv_info_ptr = &(gnss_report_ptr->expandedSvList[i].svInfo);
            }
            else {
                sv_info_ptr = &(gnss_report_ptr->svList[i]);
            }
            if((sv_info_ptr->validMask & QMI_LOC_SV_INFO_MASK_VALID_SYSTEM_V02) &&
               (sv_info_ptr->validMask & QMI_LOC_SV_INFO_MASK_VALID_GNSS_SVID_V02)
                && (sv_info_ptr->gnssSvId != 0 ))
            {
                GnssSvOptionsMask mask = 0;

                LOC_LOGv("i:%d sv-id:%d count:%d sys:%d en:0x%" PRIx64,
                    i, sv_info_ptr->gnssSvId, SvNotify.count, sv_info_ptr->system,
                    gnss_report_ptr->gnssSignalTypeList[i]);

                GnssSv &gnssSv_ref = SvNotify.gnssSvs[SvNotify.count];
                bool bSvIdIsValid = false;

                gnssSv_ref.size = sizeof(GnssSv);
                gnssSv_ref.svId = sv_info_ptr->gnssSvId;
                if (1 == gnss_report_ptr->expandedSvList_valid) {
                    gnssSv_ref.gloFrequency = gnss_report_ptr->expandedSvList[i].gloFrequency;
                }

                switch (sv_info_ptr->system) {
                case eQMI_LOC_SV_SYSTEM_GPS_V02:
                    gnssSv_ref.type = GNSS_SV_TYPE_GPS;
                    bSvIdIsValid = isValInRangeInclusive(gnssSv_ref.svId,
                                                         GPS_SV_PRN_MIN, GPS_SV_PRN_MAX);
                    break;

                case eQMI_LOC_SV_SYSTEM_GALILEO_V02:
                    gnssSv_ref.type = GNSS_SV_TYPE_GALILEO;
                    bSvIdIsValid = isValInRangeInclusive(gnssSv_ref.svId,
                                                         GAL_SV_PRN_MIN, GAL_SV_PRN_MAX);
                    break;

                case eQMI_LOC_SV_SYSTEM_SBAS_V02:
                    gnssSv_ref.type = GNSS_SV_TYPE_SBAS;
                    bSvIdIsValid = isValInRangeInclusive(gnssSv_ref.svId,
                                                         SBAS_SV_PRN_MIN, SBAS_SV_PRN_MAX);
                    break;

                // Glonass in SV report comes in range of [1, 32] or 255,
                // convert to [65, 96] or 255
                case eQMI_LOC_SV_SYSTEM_GLONASS_V02:
                    gnssSv_ref.type = GNSS_SV_TYPE_GLONASS;
                    if (!isGloSlotUnknown(sv_info_ptr->gnssSvId)) {
                        gnssSv_ref.svId = sv_info_ptr->gnssSvId + GLO_SV_PRN_MIN - 1;
                    }
                    bSvIdIsValid = isValInRangeInclusive(gnssSv_ref.svId, GLO_SV_PRN_MIN,
                                                         GLO_SV_PRN_MAX) ||
                                   isGloSlotUnknown(gnssSv_ref.svId);
                    break;

                case eQMI_LOC_SV_SYSTEM_BDS_V02:
                case eQMI_LOC_SV_SYSTEM_COMPASS_V02:
                    gnssSv_ref.type = GNSS_SV_TYPE_BEIDOU;
                    bSvIdIsValid = isValInRangeInclusive(gnssSv_ref.svId,
                                                         BDS_SV_PRN_MIN, BDS_SV_PRN_MAX);
                    break;

                case eQMI_LOC_SV_SYSTEM_QZSS_V02:
                    gnssSv_ref.type = GNSS_SV_TYPE_QZSS;
                    bSvIdIsValid = isValInRangeInclusive(gnssSv_ref.svId,
                                                         QZSS_SV_PRN_MIN, QZSS_SV_PRN_MAX);
                    break;

                case eQMI_LOC_SV_SYSTEM_NAVIC_V02:
                    gnssSv_ref.type = GNSS_SV_TYPE_NAVIC;
                    bSvIdIsValid = isValInRangeInclusive(gnssSv_ref.svId,
                                                         NAVIC_SV_PRN_MIN, NAVIC_SV_PRN_MAX);
                    break;

                default:
                    gnssSv_ref.type = GNSS_SV_TYPE_UNKNOWN;
                    break;
                }
                if (!bSvIdIsValid) {
                    memset(&gnssSv_ref, 0, sizeof(gnssSv_ref));
                    continue;
                }

                if (sv_info_ptr->validMask & QMI_LOC_SV_INFO_MASK_VALID_ELEVATION_V02) {
                    gnssSv_ref.elevation = sv_info_ptr->elevation;
                }

                if (sv_info_ptr->validMask & QMI_LOC_SV_INFO_MASK_VALID_AZIMUTH_V02) {
                    gnssSv_ref.azimuth = sv_info_ptr->azimuth;
                }

                if (sv_info_ptr->validMask &
                    QMI_LOC_SV_INFO_MASK_VALID_SVINFO_MASK_V02) {
                    if (sv_info_ptr->svInfoMask &
                        QMI_LOC_SVINFO_MASK_HAS_EPHEMERIS_V02) {
                        mask |= GNSS_SV_OPTIONS_HAS_EPHEMER_BIT;
                    }
                    if (sv_info_ptr->svInfoMask &
                        QMI_LOC_SVINFO_MASK_HAS_ALMANAC_V02) {
                        mask |= GNSS_SV_OPTIONS_HAS_ALMANAC_BIT;
                    }
                }

                mask |= GNSS_SV_OPTIONS_HAS_GNSS_SIGNAL_TYPE_BIT;
                if (gnss_report_ptr->gnssSignalTypeList_valid) {
                    if (SvNotify.count > gnss_report_ptr->gnssSignalTypeList_len - 1) {
                        LOC_LOGv("Frequency not available for this SV");
                    }
                    else {
                        if (1 == gnss_report_ptr->expandedSvList_valid) {
                            gloFrequency = gnss_report_ptr->expandedSvList[i].gloFrequency;
                            LOC_LOGv("gloFrequency = 0x%X", gloFrequency);
                        }

                        if (gnss_report_ptr->gnssSignalTypeList[i] != 0) {
                            gnssSv_ref.carrierFrequencyHz =
                                    convertSignalTypeToCarrierFrequency(
                                        gnss_report_ptr->gnssSignalTypeList[i],
                                        gloFrequency);
                            mask |= GNSS_SV_OPTIONS_HAS_CARRIER_FREQUENCY_BIT;
                            gnssSv_ref.gnssSignalTypeMask = convertQmiGnssSignalType(
                                    gnss_report_ptr->gnssSignalTypeList[i]);
                            LOC_LOGd("sv id %d, qmi signal type: 0x%" PRIx64 ", "
                                     "hal signal type: 0x%x", gnssSv_ref.svId,
                                     gnss_report_ptr->gnssSignalTypeList[i],
                                     gnssSv_ref.gnssSignalTypeMask);
                        }
                    }
                } else {
                    gnssSv_ref.gnssSignalTypeMask =
                            getDefaultGnssSignalTypeMask(sv_info_ptr->system);
                    mask |= GNSS_SV_OPTIONS_HAS_CARRIER_FREQUENCY_BIT;
                    gnssSv_ref.carrierFrequencyHz = CarrierFrequencies[gnssSv_ref.type];
                }

                if (sv_info_ptr->validMask & QMI_LOC_SV_INFO_MASK_VALID_SNR_V02) {
                    gnssSv_ref.cN0Dbhz = sv_info_ptr->snr;
                    double rfLoss = gnss_report_ptr->rfLoss[i];
                    if ((1 != gnss_report_ptr->expandedSvList_valid) ||
                        (1 != gnss_report_ptr->rfLoss_valid)) {
                        switch (gnssSv_ref.gnssSignalTypeMask) {
                        case GNSS_SIGNAL_GPS_L1CA:
                        case GNSS_SIGNAL_GPS_L1C:
                        case GNSS_SIGNAL_QZSS_L1CA:
                            rfLoss = rfLossNV[RF_LOSS_GPS_CONF]/10.0;
                            break;
                        case GNSS_SIGNAL_GPS_L5:
                        case GNSS_SIGNAL_QZSS_L5:
                            rfLoss = rfLossNV[RF_LOSS_GPS_L5_CONF]/10.0;
                            break;
                        case GNSS_SIGNAL_BEIDOU_B1I:
                            rfLoss = rfLossNV[RF_LOSS_BDS_CONF]/10.0;
                            break;
                        case GNSS_SIGNAL_BEIDOU_B2AI:
                            rfLoss = rfLossNV[RF_LOSS_BDS_B2A_CONF]/10.0;
                            break;
                        case GNSS_SIGNAL_GLONASS_G1:
                        case GNSS_SIGNAL_GLONASS_G2:
                            {
                                /* compute rfLoss based on rfLossNV[RF_LOSS_GLO_LEFT_CONF],
                                   rfLossNV[RF_LOSS_GLO_CENTER_CONF],
                                   rfLossNV[RF_LOSS_GLO_RIGHT_CONF] and gloFrequency */
                                LocApiProxyBase* locApiProxyObj = getLocApiProxy();
                                if (nullptr != locApiProxyObj &&
                                    ((gloFrequency >= 1 && gloFrequency <= 14))) {
                                    rfLoss = locApiProxyObj->getGloRfLoss(
                                                    rfLossNV[RF_LOSS_GLO_LEFT_CONF],
                                                    rfLossNV[RF_LOSS_GLO_CENTER_CONF],
                                                    rfLossNV[RF_LOSS_GLO_RIGHT_CONF],
                                                    gloFrequency);
                                }
                            }
                            break;
                        case GNSS_SIGNAL_GALILEO_E1:
                            rfLoss = rfLossNV[RF_LOSS_GAL_CONF]/10.0;
                            break;
                        case GNSS_SIGNAL_GALILEO_E5A:
                        case GNSS_SIGNAL_GALILEO_E5B:
                            rfLoss = rfLossNV[RF_LOSS_GAL_E5_CONF]/10.0;
                            break;
                        case GNSS_SIGNAL_NAVIC_L5:
                            rfLoss = rfLossNV[RF_LOSS_NAVIC_CONF]/10.0;
                            break;
                        default:
                            break;
                        }
                    }
                    LOC_LOGv("cN0Dbhz=%f rfLoss=%f gloFrequency=%d",
                             gnssSv_ref.cN0Dbhz, rfLoss, gloFrequency);
                    if (gnssSv_ref.cN0Dbhz > rfLoss) {
                        gnssSv_ref.basebandCarrierToNoiseDbHz = gnssSv_ref.cN0Dbhz - rfLoss;
                    }
                }

                gnssSv_ref.gnssSvOptionsMask = mask;
                SvNotify.count++;
            }
        }
    }

    LocApiBase::reportSv(SvNotify);
}

static Gnss_LocSvSystemEnumType getLocApiSvSystemType (qmiLocSvSystemEnumT_v02 qmiSvSystemType) {
    Gnss_LocSvSystemEnumType locSvSystemType = GNSS_LOC_SV_SYSTEM_UNKNOWN;

    switch (qmiSvSystemType) {
    case eQMI_LOC_SV_SYSTEM_GPS_V02:
        locSvSystemType = GNSS_LOC_SV_SYSTEM_GPS;
        break;

    case eQMI_LOC_SV_SYSTEM_GALILEO_V02:
        locSvSystemType = GNSS_LOC_SV_SYSTEM_GALILEO;
        break;

    case eQMI_LOC_SV_SYSTEM_SBAS_V02:
        locSvSystemType = GNSS_LOC_SV_SYSTEM_SBAS;
        break;

    case eQMI_LOC_SV_SYSTEM_GLONASS_V02:
        locSvSystemType = GNSS_LOC_SV_SYSTEM_GLONASS;
        break;

    case eQMI_LOC_SV_SYSTEM_BDS_V02:
    case eQMI_LOC_SV_SYSTEM_COMPASS_V02:
        locSvSystemType = GNSS_LOC_SV_SYSTEM_BDS;
        break;

    case eQMI_LOC_SV_SYSTEM_QZSS_V02:
        locSvSystemType = GNSS_LOC_SV_SYSTEM_QZSS;
        break;

    case eQMI_LOC_SV_SYSTEM_NAVIC_V02:
        locSvSystemType = GNSS_LOC_SV_SYSTEM_NAVIC;
        break;

    default:
        break;
    }

    return locSvSystemType;
}

/* convert satellite polynomial to loc eng format and  send the converted
   report to loc eng */
void  LocApiV02 :: reportSvPolynomial (
  const qmiLocEventGnssSvPolyIndMsgT_v02 *gnss_sv_poly_ptr)
{
  GnssSvPolynomial  svPolynomial;

  memset(&svPolynomial, 0, sizeof(GnssSvPolynomial));
  svPolynomial.size = sizeof(GnssSvPolynomial);
  svPolynomial.is_valid = 0;

  if(0 != gnss_sv_poly_ptr->gnssSvId)
  {
    svPolynomial.gnssSvId       = gnss_sv_poly_ptr->gnssSvId;
    svPolynomial.T0             = gnss_sv_poly_ptr->T0;

    if(1 == gnss_sv_poly_ptr->gloFrequency_valid)
    {
      svPolynomial.is_valid  |= ULP_GNSS_SV_POLY_BIT_GLO_FREQ;
      svPolynomial.freqNum   = gnss_sv_poly_ptr->gloFrequency;
    }
    if(1 == gnss_sv_poly_ptr->IODE_valid)
    {
      svPolynomial.is_valid  |= ULP_GNSS_SV_POLY_BIT_IODE;
      svPolynomial.iode       = gnss_sv_poly_ptr->IODE;
     }

    if(1 == gnss_sv_poly_ptr->svPosUnc_valid)
    {
      svPolynomial.is_valid |= ULP_GNSS_SV_POLY_BIT_SV_POSUNC;
      svPolynomial.svPosUnc = gnss_sv_poly_ptr->svPosUnc;
    }

    if(0 != gnss_sv_poly_ptr->svPolyFlagValid)
    {
      svPolynomial.is_valid |= ULP_GNSS_SV_POLY_BIT_FLAG;
      svPolynomial.svPolyStatusMaskValidity = gnss_sv_poly_ptr->svPolyFlagValid;
      svPolynomial.svPolyStatusMask = gnss_sv_poly_ptr->svPolyFlags;
    }

    if(1 == gnss_sv_poly_ptr->polyCoeffXYZ0_valid)
    {
      svPolynomial.is_valid |= ULP_GNSS_SV_POLY_BIT_POLYCOEFF_XYZ0;
      for(int i=0;i<GNSS_SV_POLY_XYZ_0_TH_ORDER_COEFF_MAX_SIZE;i++)
      {
        svPolynomial.polyCoeffXYZ0[i] = gnss_sv_poly_ptr->polyCoeffXYZ0[i];
      }
    }

    if(1 == gnss_sv_poly_ptr->polyCoefXYZN_valid)
    {
      svPolynomial.is_valid |= ULP_GNSS_SV_POLY_BIT_POLYCOEFF_XYZN;
      for(int i=0;i<GNSS_SV_POLY_XYZ_N_TH_ORDER_COEFF_MAX_SIZE;i++)
      {
        svPolynomial.polyCoefXYZN[i] = gnss_sv_poly_ptr->polyCoefXYZN[i];
      }
    }

    if(1 == gnss_sv_poly_ptr->polyCoefClockBias_valid)
    {

      svPolynomial.is_valid |= ULP_GNSS_SV_POLY_BIT_POLYCOEFF_OTHER;
      for(int i=0;i<GNSS_SV_POLY_SV_CLKBIAS_COEFF_MAX_SIZE;i++)
      {
        svPolynomial.polyCoefOther[i] = gnss_sv_poly_ptr->polyCoefClockBias[i];
      }
    }

    if(1 == gnss_sv_poly_ptr->ionoDot_valid)
    {
      svPolynomial.is_valid |= ULP_GNSS_SV_POLY_BIT_IONODOT;
      svPolynomial.ionoDot = gnss_sv_poly_ptr->ionoDot;
    }
    if(1 == gnss_sv_poly_ptr->ionoDelay_valid)
    {
      svPolynomial.is_valid |= ULP_GNSS_SV_POLY_BIT_IONODELAY;
      svPolynomial.ionoDelay = gnss_sv_poly_ptr->ionoDelay;
    }

    if(1 == gnss_sv_poly_ptr->sbasIonoDot_valid)
    {
      svPolynomial.is_valid |= ULP_GNSS_SV_POLY_BIT_SBAS_IONODOT;
      svPolynomial.sbasIonoDot = gnss_sv_poly_ptr->sbasIonoDot;
    }
    if(1 == gnss_sv_poly_ptr->sbasIonoDelay_valid)
    {
      svPolynomial.is_valid |= ULP_GNSS_SV_POLY_BIT_SBAS_IONODELAY;
      svPolynomial.sbasIonoDelay = gnss_sv_poly_ptr->sbasIonoDelay;
    }
    if(1 == gnss_sv_poly_ptr->tropoDelay_valid)
    {
      svPolynomial.is_valid |= ULP_GNSS_SV_POLY_BIT_TROPODELAY;
      svPolynomial.tropoDelay = gnss_sv_poly_ptr->tropoDelay;
    }
    if(1 == gnss_sv_poly_ptr->elevation_valid)
    {
      svPolynomial.is_valid |= ULP_GNSS_SV_POLY_BIT_ELEVATION;
      svPolynomial.elevation = gnss_sv_poly_ptr->elevation;
    }
    if(1 == gnss_sv_poly_ptr->elevationDot_valid)
    {
      svPolynomial.is_valid |= ULP_GNSS_SV_POLY_BIT_ELEVATIONDOT;
      svPolynomial.elevationDot = gnss_sv_poly_ptr->elevationDot;
    }
    if(1 == gnss_sv_poly_ptr->elenationUnc_valid)
    {
      svPolynomial.is_valid |= ULP_GNSS_SV_POLY_BIT_ELEVATIONUNC;
      svPolynomial.elevationUnc = gnss_sv_poly_ptr->elenationUnc;
    }
    if(1 == gnss_sv_poly_ptr->velCoef_valid)
    {
      svPolynomial.is_valid |= ULP_GNSS_SV_POLY_BIT_VELO_COEFF;
      for(int i=0;i<GNSS_SV_POLY_VELOCITY_COEF_MAX_SIZE;i++)
      {
        svPolynomial.velCoef[i] = gnss_sv_poly_ptr->velCoef[i];
      }
    }
    if(1 == gnss_sv_poly_ptr->enhancedIOD_valid)
    {
      svPolynomial.is_valid |= ULP_GNSS_SV_POLY_BIT_ENHANCED_IOD;
      svPolynomial.enhancedIOD = gnss_sv_poly_ptr->enhancedIOD;
    }

    if(1 == gnss_sv_poly_ptr->gpsIscL1ca_valid)
    {
        svPolynomial.is_valid |= ULP_GNSS_SV_POLY_BIT_GPS_ISC_L1CA;
        svPolynomial.gpsIscL1ca = gnss_sv_poly_ptr->gpsIscL1ca;
    }

    if(1 == gnss_sv_poly_ptr->gpsIscL2c_valid)
    {
        svPolynomial.is_valid |= ULP_GNSS_SV_POLY_BIT_GPS_ISC_L2C;
        svPolynomial.gpsIscL2c = gnss_sv_poly_ptr->gpsIscL2c;
    }

    if(1 == gnss_sv_poly_ptr->gpsIscL5I5_valid)
    {
        svPolynomial.is_valid |= ULP_GNSS_SV_POLY_BIT_GPS_ISC_L5I5;
        svPolynomial.gpsIscL5I5 = gnss_sv_poly_ptr->gpsIscL5I5;
    }

    if(1 == gnss_sv_poly_ptr->gpsIscL5Q5_valid)
    {
        svPolynomial.is_valid |= ULP_GNSS_SV_POLY_BIT_GPS_ISC_L5Q5;
        svPolynomial.gpsIscL5Q5 = gnss_sv_poly_ptr->gpsIscL5Q5;
    }

    if(1 == gnss_sv_poly_ptr->gpsTgd_valid)
    {
        svPolynomial.is_valid |= ULP_GNSS_SV_POLY_BIT_GPS_TGD;
        svPolynomial.gpsTgd = gnss_sv_poly_ptr->gpsTgd;
    }

    if(1 == gnss_sv_poly_ptr->gloTgdG1G2_valid)
    {
        svPolynomial.is_valid |= ULP_GNSS_SV_POLY_BIT_GLO_TGD_G1G2;
        svPolynomial.gloTgdG1G2 = gnss_sv_poly_ptr->gloTgdG1G2;
    }

    if(1 == gnss_sv_poly_ptr->bdsTgdB1_valid)
    {
        svPolynomial.is_valid |= ULP_GNSS_SV_POLY_BIT_BDS_TGD_B1;
        svPolynomial.bdsTgdB1 = gnss_sv_poly_ptr->bdsTgdB1;
    }

    if(1 == gnss_sv_poly_ptr->bdsTgdB2_valid)
    {
        svPolynomial.is_valid |= ULP_GNSS_SV_POLY_BIT_BDS_TGD_B2;
        svPolynomial.bdsTgdB2= gnss_sv_poly_ptr->bdsTgdB2;
    }

    if(1 == gnss_sv_poly_ptr->bdsTgdB2a_valid)
    {
        svPolynomial.is_valid |= ULP_GNSS_SV_POLY_BIT_BDS_TGD_B2A;
        svPolynomial.bdsTgdB2a = gnss_sv_poly_ptr->bdsTgdB2a;
    }

    if(1 == gnss_sv_poly_ptr->bdsIscB2a_valid)
    {
        svPolynomial.is_valid |= ULP_GNSS_SV_POLY_BIT_BDS_ISC_B2A;
        svPolynomial.bdsIscB2a = gnss_sv_poly_ptr->bdsIscB2a;
    }

    if(1 == gnss_sv_poly_ptr->galBgdE1E5a_valid)
    {
        svPolynomial.is_valid |= ULP_GNSS_SV_POLY_BIT_GAL_BGD_E1E5A;
        svPolynomial.galBgdE1E5a = gnss_sv_poly_ptr->galBgdE1E5a;
    }

    if(1 == gnss_sv_poly_ptr->galBgdE1E5b_valid)
    {
        svPolynomial.is_valid |= ULP_GNSS_SV_POLY_BIT_GAL_BGD_E1E5B;
        svPolynomial.galBgdE1E5b = gnss_sv_poly_ptr->galBgdE1E5b;
    }

    if(1 == gnss_sv_poly_ptr->navicTgdL5_valid)
    {
        svPolynomial.is_valid |= ULP_GNSS_SV_POLY_BIT_NAVIC_TGD_L5;
        svPolynomial.navicTgdL5 = gnss_sv_poly_ptr->navicTgdL5;
    }

    LocApiBase::reportSvPolynomial(svPolynomial);

    LOC_LOGV("[SV_POLY_QMI] SV-Id:%d\n", svPolynomial.gnssSvId);
  }
  else
  {
     LOC_LOGV("[SV_POLY]  INVALID SV-Id:%d", svPolynomial.gnssSvId);
  }
} //reportSvPolynomial

void LocApiV02::reportLocEvent(const qmiLocEventReportIndMsgT_v02 *event_report_ptr)
{
    GnssAidingData aidingData;
    memset(&aidingData, 0, sizeof(aidingData));
    LOC_LOGe("Loc event report: %" PRIu64 " KlobucharIonoMode_valid:%d: leapSec_valid:%d: "
             "tauC_valid:%d featureStatusReport_valid: %d featureStatusReport: %" PRIu64 "",
            event_report_ptr->eventReport, event_report_ptr->klobucharIonoModel_valid,
            event_report_ptr->leapSec_valid, event_report_ptr->tauC_valid,
            event_report_ptr->featureStatusReport_valid, event_report_ptr->featureStatusReport);

    if (event_report_ptr->eventReport & QMI_LOC_DELETE_GPS_EPHEMERIS_ALL_V02) {
        aidingData.sv.svMask |= GNSS_AIDING_DATA_SV_EPHEMERIS_BIT;
        aidingData.sv.svTypeMask |= GNSS_AIDING_DATA_SV_TYPE_GPS_BIT;
    }

    if (event_report_ptr->eventReport & QMI_LOC_DELETE_GLO_EPHEMERIS_ALL_V02) {
        aidingData.sv.svMask |= GNSS_AIDING_DATA_SV_EPHEMERIS_BIT;
        aidingData.sv.svTypeMask |= GNSS_AIDING_DATA_SV_TYPE_GLONASS_BIT;
    }

    if (event_report_ptr->eventReport & QMI_LOC_DELETE_BDS_EPHEMERIS_ALL_V02) {
        aidingData.sv.svMask |= GNSS_AIDING_DATA_SV_EPHEMERIS_BIT;
        aidingData.sv.svTypeMask |= GNSS_AIDING_DATA_SV_TYPE_BEIDOU_BIT;
    }

    if (event_report_ptr->eventReport & QMI_LOC_DELETE_GAL_EPHEMERIS_ALL_V02) {
        aidingData.sv.svMask |= GNSS_AIDING_DATA_SV_EPHEMERIS_BIT;
        aidingData.sv.svTypeMask |= GNSS_AIDING_DATA_SV_TYPE_GALILEO_BIT;
    }

    if (event_report_ptr->eventReport & QMI_LOC_DELETE_QZSS_EPHEMERIS_ALL_V02) {
        aidingData.sv.svMask |= GNSS_AIDING_DATA_SV_EPHEMERIS_BIT;
        aidingData.sv.svTypeMask |= GNSS_AIDING_DATA_SV_TYPE_QZSS_BIT;
    }

    if (event_report_ptr->eventReport & QMI_LOC_DELETE_GPS_SV_POLY_ALL_V02) {
        aidingData.sv.svMask |= GNSS_AIDING_DATA_SV_POLY_BIT;
        aidingData.sv.svTypeMask |= GNSS_AIDING_DATA_SV_TYPE_GPS_BIT;
    }

    if (event_report_ptr->eventReport & QMI_LOC_DELETE_GLO_SV_POLY_ALL_V02) {
        aidingData.sv.svMask |= GNSS_AIDING_DATA_SV_POLY_BIT;
        aidingData.sv.svTypeMask |= GNSS_AIDING_DATA_SV_TYPE_GLONASS_BIT;
    }

    if (event_report_ptr->eventReport & QMI_LOC_DELETE_BDS_SV_POLY_ALL_V02) {
        aidingData.sv.svMask |= GNSS_AIDING_DATA_SV_POLY_BIT;
        aidingData.sv.svTypeMask |= GNSS_AIDING_DATA_SV_TYPE_BEIDOU_BIT;
    }

    if (event_report_ptr->eventReport & QMI_LOC_DELETE_GAL_SV_POLY_ALL_V02) {
        aidingData.sv.svMask |= GNSS_AIDING_DATA_SV_POLY_BIT;
        aidingData.sv.svTypeMask |= GNSS_AIDING_DATA_SV_TYPE_GALILEO_BIT;
    }

    if (event_report_ptr->eventReport & QMI_LOC_DELETE_QZSS_SV_POLY_ALL_V02) {
        aidingData.sv.svMask |= GNSS_AIDING_DATA_SV_POLY_BIT;
        aidingData.sv.svTypeMask |= GNSS_AIDING_DATA_SV_TYPE_QZSS_BIT;
    }

    if (event_report_ptr->eventReport & QMI_LOC_DELETE_GPS_IONO_ALL_V02) {
        aidingData.sv.svMask |= GNSS_AIDING_DATA_SV_IONOSPHERE_BIT;
        aidingData.sv.svTypeMask |= GNSS_AIDING_DATA_SV_TYPE_GPS_BIT;
    }

    if (event_report_ptr->eventReport & QMI_LOC_DELETE_GLO_IONO_ALL_V02) {
        aidingData.sv.svMask |= GNSS_AIDING_DATA_SV_IONOSPHERE_BIT;
        aidingData.sv.svTypeMask |= GNSS_AIDING_DATA_SV_TYPE_GLONASS_BIT;
    }

    if (event_report_ptr->eventReport & QMI_LOC_DELETE_BDS_IONO_ALL_V02) {
        aidingData.sv.svMask |= GNSS_AIDING_DATA_SV_IONOSPHERE_BIT;
        aidingData.sv.svTypeMask |= GNSS_AIDING_DATA_SV_TYPE_BEIDOU_BIT;
    }

    if (event_report_ptr->eventReport & QMI_LOC_DELETE_GAL_IONO_ALL_V02) {
        aidingData.sv.svMask |= GNSS_AIDING_DATA_SV_IONOSPHERE_BIT;
        aidingData.sv.svTypeMask |= GNSS_AIDING_DATA_SV_TYPE_GALILEO_BIT;
    }

    if (event_report_ptr->eventReport & QMI_LOC_DELETE_QZSS_IONO_ALL_V02) {
        aidingData.sv.svMask |= GNSS_AIDING_DATA_SV_IONOSPHERE_BIT;
        aidingData.sv.svTypeMask |= GNSS_AIDING_DATA_SV_TYPE_QZSS_BIT;
    }

    if ((aidingData.sv.svMask != 0) && (aidingData.sv.svTypeMask != 0)) {
        LocApiBase::reportDeleteAidingDataEvent(aidingData);
    }

    // report Klobuchar IonoModel
    if (event_report_ptr->klobucharIonoModel_valid) {
        GnssKlobucharIonoModel klobucharIonoModel;
        memset(&klobucharIonoModel, 0, sizeof(klobucharIonoModel));

        if (event_report_ptr->gpsSystemTime_valid) {
            klobucharIonoModel.isSystemTimeValid = true;
            populateGpsTimeOfReport(event_report_ptr->gpsSystemTime, klobucharIonoModel.systemTime);
        }

        switch(event_report_ptr->klobucharIonoModel.dataSource) {
            case eQMI_LOC_SV_SYSTEM_GPS_V02:
                klobucharIonoModel.gnssConstellation = GNSS_LOC_SV_SYSTEM_GPS;
                break;
            case eQMI_LOC_SV_SYSTEM_GALILEO_V02:
                klobucharIonoModel.gnssConstellation = GNSS_LOC_SV_SYSTEM_GALILEO;
                break;
            case eQMI_LOC_SV_SYSTEM_SBAS_V02:
                klobucharIonoModel.gnssConstellation = GNSS_LOC_SV_SYSTEM_SBAS;
                break;
            case eQMI_LOC_SV_SYSTEM_GLONASS_V02:
                klobucharIonoModel.gnssConstellation = GNSS_LOC_SV_SYSTEM_GLONASS;
                break;
            case eQMI_LOC_SV_SYSTEM_BDS_V02:
            case eQMI_LOC_SV_SYSTEM_COMPASS_V02:
                klobucharIonoModel.gnssConstellation = GNSS_LOC_SV_SYSTEM_BDS;
                break;
            case eQMI_LOC_SV_SYSTEM_QZSS_V02:
                klobucharIonoModel.gnssConstellation = GNSS_LOC_SV_SYSTEM_QZSS;
                break;
        }

        klobucharIonoModel.alpha0 = event_report_ptr->klobucharIonoModel.alpha0;
        klobucharIonoModel.alpha1 = event_report_ptr->klobucharIonoModel.alpha1;
        klobucharIonoModel.alpha2 = event_report_ptr->klobucharIonoModel.alpha2;
        klobucharIonoModel.alpha3 = event_report_ptr->klobucharIonoModel.alpha3;
        klobucharIonoModel.beta0  = event_report_ptr->klobucharIonoModel.beta0;
        klobucharIonoModel.beta1 = event_report_ptr->klobucharIonoModel.beta1;
        klobucharIonoModel.beta2 = event_report_ptr->klobucharIonoModel.beta2;
        klobucharIonoModel.beta3 = event_report_ptr->klobucharIonoModel.beta3;
        LOC_LOGd("iono model: %d:%f:%f:%f:%f:%f:%f:%f:%f:%d",
            klobucharIonoModel.gnssConstellation,  klobucharIonoModel.alpha0,
            klobucharIonoModel.alpha1, klobucharIonoModel.alpha2, klobucharIonoModel.alpha3,
            klobucharIonoModel.beta0, klobucharIonoModel.beta1, klobucharIonoModel.beta2,
            klobucharIonoModel.beta3, klobucharIonoModel.isSystemTimeValid);

        LocApiBase::reportKlobucharIonoModel(klobucharIonoModel);
    }

    // report gnss additional system info
    GnssAdditionalSystemInfo additionalSystemInfo;
    memset(&additionalSystemInfo, 0, sizeof(additionalSystemInfo));
    if (event_report_ptr->leapSec_valid) {
        additionalSystemInfo.validityMask |= GNSS_ADDITIONAL_SYSTEMINFO_HAS_LEAP_SEC;
        additionalSystemInfo.leapSec = event_report_ptr->leapSec;
        LOC_LOGd("LeapSec: %d", event_report_ptr->leapSec);
    }
    if (event_report_ptr->tauC_valid) {
        additionalSystemInfo.validityMask |= GNSS_ADDITIONAL_SYSTEMINFO_HAS_TAUC;
        additionalSystemInfo.tauC = event_report_ptr->tauC;
        LOC_LOGd("tauC: %lf", event_report_ptr->tauC);
    }

    if (additionalSystemInfo.validityMask && event_report_ptr->gpsSystemTime_valid) {
        additionalSystemInfo.isSystemTimeValid = true;
        populateGpsTimeOfReport(event_report_ptr->gpsSystemTime, additionalSystemInfo.systemTime);
        LocApiBase::reportGnssAdditionalSystemInfo(additionalSystemInfo);
    }
    if (event_report_ptr->featureStatusReport_valid) {
        std::unordered_map<LocationQwesFeatureType, bool> featureMap;
        populateFeatureStatusReport(event_report_ptr->featureStatusReport, featureMap);
        LocApiBase::reportQwesCapabilities(featureMap);
    }
}

void LocApiV02::populateFeatureStatusReport
(
        const qmiLocFeaturesStatusMaskT_v02 &featureStatusReport,
        std::unordered_map<LocationQwesFeatureType, bool> &featureMap
)
{
    if (featureStatusReport & QMI_LOC_FEATURE_STATUS_CARRIER_PHASE_V02) {
        featureMap[LOCATION_QWES_FEATURE_TYPE_CARRIER_PHASE] = true;
    } else {
        featureMap[LOCATION_QWES_FEATURE_TYPE_CARRIER_PHASE] = false;
    }
    if (featureStatusReport & QMI_LOC_FEATURE_STATUS_SV_POLYNOMIALS_V02) {
        featureMap[LOCATION_QWES_FEATURE_TYPE_SV_POLYNOMIAL] = true;
    } else {
        featureMap[LOCATION_QWES_FEATURE_TYPE_SV_POLYNOMIAL] = false;
    }
    if (featureStatusReport & QMI_LOC_FEATURE_STATUS_SV_EPHEMERIS_V02) {
        featureMap[LOCATION_QWES_FEATURE_TYPE_SV_EPH] = true;
    } else {
        featureMap[LOCATION_QWES_FEATURE_TYPE_SV_EPH] = false;
    }
    if (featureStatusReport & QMI_LOC_FEATURE_STATUS_SINGLE_FREQUENCY_V02) {
        featureMap[LOCATION_QWES_FEATURE_TYPE_GNSS_SINGLE_FREQUENCY] = true;
    } else {
        featureMap[LOCATION_QWES_FEATURE_TYPE_GNSS_SINGLE_FREQUENCY] = false;
    }
    if (featureStatusReport & QMI_LOC_FEATURE_STATUS_MULTI_FREQUENCY_V02) {
        featureMap[LOCATION_QWES_FEATURE_TYPE_GNSS_MULTI_FREQUENCY] = true;
    } else {
        featureMap[LOCATION_QWES_FEATURE_TYPE_GNSS_MULTI_FREQUENCY] = false;
    }
    if (featureStatusReport & QMI_LOC_FEATURE_STATUS_TIME_FREQUENCY_V02) {
        featureMap[LOCATION_QWES_FEATURE_TYPE_TIME_FREQUENCY] = true;
    } else {
        featureMap[LOCATION_QWES_FEATURE_TYPE_TIME_FREQUENCY] = false;
    }
    if (featureStatusReport & QMI_LOC_FEATURE_STATUS_TIME_UNCERTAINTY_V02) {
        featureMap[LOCATION_QWES_FEATURE_TYPE_TIME_UNCERTAINTY] = true;
    } else {
        featureMap[LOCATION_QWES_FEATURE_TYPE_TIME_UNCERTAINTY] = false;
    }
    if (featureStatusReport & QMI_LOC_FEATURE_STATUS_CLOCK_ESTIMATE_V02) {
        featureMap[LOCATION_QWES_FEATURE_TYPE_CLOCK_ESTIMATE] = true;
    } else {
        featureMap[LOCATION_QWES_FEATURE_TYPE_CLOCK_ESTIMATE] = false;
    }

}

void LocApiV02::reportSvEphemeris (
        uint32_t eventId, const locClientEventIndUnionType &eventPayload) {

    GnssSvEphemerisReport svEphemeris;
    memset(&svEphemeris, 0, sizeof(svEphemeris));

    switch (eventId)
    {
        case QMI_LOC_EVENT_GPS_EPHEMERIS_REPORT_IND_V02:
            svEphemeris.gnssConstellation = GNSS_LOC_SV_SYSTEM_GPS;
            populateGpsEphemeris(eventPayload.pGpsEphemerisReportEvent, svEphemeris);
            break;
        case QMI_LOC_EVENT_GLONASS_EPHEMERIS_REPORT_IND_V02:
            svEphemeris.gnssConstellation = GNSS_LOC_SV_SYSTEM_GLONASS;
            populateGlonassEphemeris(eventPayload.pGloEphemerisReportEvent, svEphemeris);
            break;
        case QMI_LOC_EVENT_BDS_EPHEMERIS_REPORT_IND_V02:
            svEphemeris.gnssConstellation = GNSS_LOC_SV_SYSTEM_BDS;
            populateBdsEphemeris(eventPayload.pBdsEphemerisReportEvent, svEphemeris);
            break;
        case QMI_LOC_EVENT_GALILEO_EPHEMERIS_REPORT_IND_V02:
            svEphemeris.gnssConstellation = GNSS_LOC_SV_SYSTEM_GALILEO;
            populateGalEphemeris(eventPayload.pGalEphemerisReportEvent, svEphemeris);
            break;
        case QMI_LOC_EVENT_QZSS_EPHEMERIS_REPORT_IND_V02:
            svEphemeris.gnssConstellation = GNSS_LOC_SV_SYSTEM_QZSS;
            populateQzssEphemeris(eventPayload.pQzssEphemerisReportEvent, svEphemeris);
    }

    LocApiBase::reportSvEphemeris(svEphemeris);
}

void LocApiV02::populateGpsTimeOfReport(const qmiLocGnssTimeStructT_v02 &inGpsSystemTime,
        GnssSystemTimeStructType& outGpsSystemTime) {

    outGpsSystemTime.validityMask = GNSS_SYSTEM_TIME_WEEK_VALID |  GNSS_SYSTEM_TIME_WEEK_MS_VALID |
            GNSS_SYSTEM_CLK_TIME_BIAS_VALID | GNSS_SYSTEM_CLK_TIME_BIAS_UNC_VALID;

    outGpsSystemTime.systemWeek = inGpsSystemTime.systemWeek;
    outGpsSystemTime.systemMsec = inGpsSystemTime.systemMsec;
    outGpsSystemTime.systemClkTimeBias = inGpsSystemTime.systemClkTimeBias;
    outGpsSystemTime.systemClkTimeUncMs = inGpsSystemTime.systemClkTimeUncMs;
}

void LocApiV02::populateCommonEphemeris(const qmiLocEphGnssDataStructT_v02 &receivedEph,
        GnssEphCommon &ephToFill)
{
    LOC_LOGv("Eph received for sv-id: %d action:%d", receivedEph.gnssSvId,
            receivedEph.updateAction);

    ephToFill.gnssSvId = receivedEph.gnssSvId;
    switch(receivedEph.updateAction) {
        case eQMI_LOC_UPDATE_EPH_SRC_UNKNOWN_V02:
            ephToFill.updateAction = GNSS_EPH_ACTION_UPDATE_SRC_UNKNOWN_V02;
            break;
        case eQMI_LOC_UPDATE_EPH_SRC_OTA_V02:
            ephToFill.updateAction = GNSS_EPH_ACTION_UPDATE_SRC_OTA_V02;
            break;
        case eQMI_LOC_UPDATE_EPH_SRC_NETWORK_V02:
            ephToFill.updateAction = GNSS_EPH_ACTION_UPDATE_SRC_NETWORK_V02;
            break;
        case eQMI_LOC_DELETE_EPH_SRC_UNKNOWN_V02:
            ephToFill.updateAction = GNSS_EPH_ACTION_DELETE_SRC_UNKNOWN_V02;
            break;
        case eQMI_LOC_DELETE_EPH_SRC_NETWORK_V02:
            ephToFill.updateAction = GNSS_EPH_ACTION_DELETE_SRC_NETWORK_V02;
            break;
        case eQMI_LOC_DELETE_EPH_SRC_OTA_V02:
            ephToFill.updateAction = GNSS_EPH_ACTION_DELETE_SRC_OTA_V02;
            break;
    }

    ephToFill.IODE = receivedEph.IODE;
    ephToFill.aSqrt = receivedEph.aSqrt;
    ephToFill.deltaN = receivedEph.deltaN;
    ephToFill.m0 = receivedEph.m0;
    ephToFill.eccentricity = receivedEph.eccentricity;
    ephToFill.omega0 = receivedEph.omega0;
    ephToFill.i0 = receivedEph.i0;
    ephToFill.omega = receivedEph.omega;
    ephToFill.omegaDot = receivedEph.omegaDot;
    ephToFill.iDot = receivedEph.iDot;
    ephToFill.cUc = receivedEph.cUc;
    ephToFill.cUs = receivedEph.cUs;
    ephToFill.cRc = receivedEph.cRc;
    ephToFill.cRs = receivedEph.cRs;
    ephToFill.cIc = receivedEph.cIc;
    ephToFill.cIs = receivedEph.cIs;
    ephToFill.toe = receivedEph.toe;
    ephToFill.toc = receivedEph.toc;
    ephToFill.af0 = receivedEph.af0;
    ephToFill.af1 = receivedEph.af1;
    ephToFill.af2 = receivedEph.af2;
}


void LocApiV02::populateGpsEphemeris(
        const qmiLocGpsEphemerisReportIndMsgT_v02 *gpsEphemeris,
        GnssSvEphemerisReport &svEphemeris)
{
    LOC_LOGd("GPS Ephemeris Received: Len= %d: systemTime_valid%d",
            gpsEphemeris->gpsEphemerisList_len, gpsEphemeris->gpsSystemTime_valid);
    svEphemeris.ephInfo.gpsEphemeris.numOfEphemeris = gpsEphemeris->gpsEphemerisList_len;

    if (gpsEphemeris->gpsSystemTime_valid) {
        svEphemeris.isSystemTimeValid = true;
        populateGpsTimeOfReport(gpsEphemeris->gpsSystemTime, svEphemeris.systemTime);
    }

    for (uint32_t i =0; i < gpsEphemeris->gpsEphemerisList_len; i++) {
        const qmiLocGpsEphemerisT_v02 &receivedGpsEphemeris = gpsEphemeris->gpsEphemerisList[i];
        GpsEphemeris &gpsEphemerisToFill = svEphemeris.ephInfo.gpsEphemeris.gpsEphemerisData[i];

        populateCommonEphemeris(receivedGpsEphemeris.commonEphemerisData,
                gpsEphemerisToFill.commonEphemerisData);

        gpsEphemerisToFill.signalHealth = receivedGpsEphemeris.signalHealth;
        gpsEphemerisToFill.URAI = receivedGpsEphemeris.URAI;
        gpsEphemerisToFill.codeL2 = receivedGpsEphemeris.codeL2;
        gpsEphemerisToFill.dataFlagL2P = receivedGpsEphemeris.dataFlagL2P;
        gpsEphemerisToFill.tgd = receivedGpsEphemeris.tgd;
        gpsEphemerisToFill.fitInterval = receivedGpsEphemeris.fitInterval;
        gpsEphemerisToFill.IODC = receivedGpsEphemeris.IODC;
    }
}

void LocApiV02::populateGlonassEphemeris(const qmiLocGloEphemerisReportIndMsgT_v02 *gloEphemeris,
        GnssSvEphemerisReport &svEphemeris)
{
    LOC_LOGd("GLO Ephemeris Received: Len= %d: systemTime_valid%d",
            gloEphemeris->gloEphemerisList_len, gloEphemeris->gpsSystemTime_valid);
    svEphemeris.ephInfo.glonassEphemeris.numOfEphemeris = gloEphemeris->gloEphemerisList_len;

    if (gloEphemeris->gpsSystemTime_valid) {
        svEphemeris.isSystemTimeValid = true;
        populateGpsTimeOfReport(gloEphemeris->gpsSystemTime, svEphemeris.systemTime);
    }

    for (uint32_t i =0; i < gloEphemeris->gloEphemerisList_len; i++) {
        const qmiLocGloEphemerisT_v02 &receivedGloEphemeris = gloEphemeris->gloEphemerisList[i];
        GlonassEphemeris &gloEphemerisToFill = svEphemeris.ephInfo.glonassEphemeris.gloEphemerisData[i];

        LOC_LOGv("Eph received for sv-id: %d action:%d", receivedGloEphemeris.gnssSvId,
            receivedGloEphemeris.updateAction);

        gloEphemerisToFill.gnssSvId = receivedGloEphemeris.gnssSvId;
        switch(receivedGloEphemeris.updateAction) {
            case eQMI_LOC_UPDATE_EPH_SRC_UNKNOWN_V02:
                gloEphemerisToFill.updateAction = GNSS_EPH_ACTION_UPDATE_SRC_UNKNOWN_V02;
                break;
            case eQMI_LOC_UPDATE_EPH_SRC_OTA_V02:
                gloEphemerisToFill.updateAction = GNSS_EPH_ACTION_UPDATE_SRC_OTA_V02;
                break;
            case eQMI_LOC_UPDATE_EPH_SRC_NETWORK_V02:
                gloEphemerisToFill.updateAction = GNSS_EPH_ACTION_UPDATE_SRC_NETWORK_V02;
                break;
            case eQMI_LOC_DELETE_EPH_SRC_UNKNOWN_V02:
                gloEphemerisToFill.updateAction = GNSS_EPH_ACTION_DELETE_SRC_UNKNOWN_V02;
                break;
            case eQMI_LOC_DELETE_EPH_SRC_NETWORK_V02:
                gloEphemerisToFill.updateAction = GNSS_EPH_ACTION_DELETE_SRC_NETWORK_V02;
                break;
            case eQMI_LOC_DELETE_EPH_SRC_OTA_V02:
                gloEphemerisToFill.updateAction = GNSS_EPH_ACTION_DELETE_SRC_OTA_V02;
                break;
        }

        gloEphemerisToFill.bnHealth = receivedGloEphemeris.bnHealth;
        gloEphemerisToFill.lnHealth = receivedGloEphemeris.lnHealth;
        gloEphemerisToFill.tb = receivedGloEphemeris.tb;
        gloEphemerisToFill.ft = receivedGloEphemeris.ft;
        gloEphemerisToFill.gloM = receivedGloEphemeris.gloM;
        gloEphemerisToFill.enAge = receivedGloEphemeris.enAge;
        gloEphemerisToFill.gloFrequency = receivedGloEphemeris.gloFrequency;
        gloEphemerisToFill.p1 = receivedGloEphemeris.p1;
        gloEphemerisToFill.p2 = receivedGloEphemeris.p2;
        gloEphemerisToFill.deltaTau = receivedGloEphemeris.deltaTau;
        memcpy(gloEphemerisToFill.position, receivedGloEphemeris.position,
              sizeof(*receivedGloEphemeris.position) * 3);
        memcpy(gloEphemerisToFill.velocity, receivedGloEphemeris.velocity,
              sizeof(*receivedGloEphemeris.velocity) * 3);
        memcpy(gloEphemerisToFill.acceleration, receivedGloEphemeris.acceleration,
              sizeof(*receivedGloEphemeris.acceleration) * 3);
        gloEphemerisToFill.tauN = receivedGloEphemeris.tauN;
        gloEphemerisToFill.gamma = receivedGloEphemeris.gamma;
        gloEphemerisToFill.toe = receivedGloEphemeris.toe;
        gloEphemerisToFill.nt = receivedGloEphemeris.nt;
    }
}

void LocApiV02::populateBdsEphemeris(const qmiLocBdsEphemerisReportIndMsgT_v02 *bdsEphemeris,
        GnssSvEphemerisReport &svEphemeris)
{
    LOC_LOGd("BDS Ephemeris Received: Len= %d: systemTime_valid%d",
            bdsEphemeris->bdsEphemerisList_len, bdsEphemeris->gpsSystemTime_valid);
    svEphemeris.ephInfo.bdsEphemeris.numOfEphemeris = bdsEphemeris->bdsEphemerisList_len;

    if (bdsEphemeris->gpsSystemTime_valid) {
        svEphemeris.isSystemTimeValid = true;
        populateGpsTimeOfReport(bdsEphemeris->gpsSystemTime, svEphemeris.systemTime);
    }


    for (uint32_t i =0; i < bdsEphemeris->bdsEphemerisList_len; i++) {
        const qmiLocBdsEphemerisT_v02 &receivedBdsEphemeris = bdsEphemeris->bdsEphemerisList[i];
        BdsEphemeris &bdsEphemerisToFill = svEphemeris.ephInfo.bdsEphemeris.bdsEphemerisData[i];

        populateCommonEphemeris(receivedBdsEphemeris.commonEphemerisData,
                bdsEphemerisToFill.commonEphemerisData);

        bdsEphemerisToFill.svHealth = receivedBdsEphemeris.svHealth;
        bdsEphemerisToFill.AODC = receivedBdsEphemeris.AODC;
        bdsEphemerisToFill.tgd1 = receivedBdsEphemeris.tgd1;
        bdsEphemerisToFill.tgd2 = receivedBdsEphemeris.tgd2;
        bdsEphemerisToFill.URAI = receivedBdsEphemeris.URAI;
    }
}

void LocApiV02::populateGalEphemeris(const qmiLocGalEphemerisReportIndMsgT_v02 *galEphemeris,
        GnssSvEphemerisReport &svEphemeris)
{
    LOC_LOGd("GAL Ephemeris Received: Len= %d: systemTime_valid%d",
            galEphemeris->galEphemerisList_len, galEphemeris->gpsSystemTime_valid);
    svEphemeris.ephInfo.galileoEphemeris.numOfEphemeris = galEphemeris->galEphemerisList_len;

    if (galEphemeris->gpsSystemTime_valid) {
        svEphemeris.isSystemTimeValid = true;
        populateGpsTimeOfReport(galEphemeris->gpsSystemTime, svEphemeris.systemTime);
    }


    for (uint32_t i =0; i < galEphemeris->galEphemerisList_len; i++) {
        const qmiLocGalEphemerisT_v02 &receivedGalEphemeris = galEphemeris->galEphemerisList[i];
        GalileoEphemeris &galEphemerisToFill = svEphemeris.ephInfo.galileoEphemeris.galEphemerisData[i];

        populateCommonEphemeris(receivedGalEphemeris.commonEphemerisData,
                galEphemerisToFill.commonEphemerisData);

        switch (receivedGalEphemeris.dataSourceSignal) {
            case eQMI_LOC_GAL_EPH_SIGNAL_SRC_UNKNOWN_V02:
                galEphemerisToFill.dataSourceSignal = GAL_EPH_SIGNAL_SRC_UNKNOWN_V02;
                break;
            case eQMI_LOC_GAL_EPH_SIGNAL_SRC_E1B_V02:
                galEphemerisToFill.dataSourceSignal = GAL_EPH_SIGNAL_SRC_E1B_V02;
                break;
            case eQMI_LOC_GAL_EPH_SIGNAL_SRC_E5A_V02:
                galEphemerisToFill.dataSourceSignal = GAL_EPH_SIGNAL_SRC_E5A_V02;
                break;
            case eQMI_LOC_GAL_EPH_SIGNAL_SRC_E5B_V02:
                galEphemerisToFill.dataSourceSignal = GAL_EPH_SIGNAL_SRC_E5B_V02;
        }

        galEphemerisToFill.sisIndex = receivedGalEphemeris.sisIndex;
        galEphemerisToFill.bgdE1E5a = receivedGalEphemeris.bgdE1E5a;
        galEphemerisToFill.bgdE1E5b = receivedGalEphemeris.bgdE1E5b;
        galEphemerisToFill.svHealth = receivedGalEphemeris.svHealth;
    }
}

void LocApiV02::populateQzssEphemeris(const qmiLocQzssEphemerisReportIndMsgT_v02 *qzssEphemeris,
        GnssSvEphemerisReport &svEphemeris)
{
    LOC_LOGd("QZSS Ephemeris Received: Len= %d: systemTime_valid%d",
            qzssEphemeris->qzssEphemerisList_len, qzssEphemeris->gpsSystemTime_valid);
    svEphemeris.ephInfo.qzssEphemeris.numOfEphemeris = qzssEphemeris->qzssEphemerisList_len;

    if (qzssEphemeris->gpsSystemTime_valid) {
        svEphemeris.isSystemTimeValid = true;
        populateGpsTimeOfReport(qzssEphemeris->gpsSystemTime, svEphemeris.systemTime);
    }


    for (uint32_t i =0; i < qzssEphemeris->qzssEphemerisList_len; i++) {
        const qmiLocGpsEphemerisT_v02 &receivedQzssEphemeris = qzssEphemeris->qzssEphemerisList[i];
        GpsEphemeris &qzssEphemerisToFill = svEphemeris.ephInfo.qzssEphemeris.qzssEphemerisData[i];

        populateCommonEphemeris(receivedQzssEphemeris.commonEphemerisData,
                qzssEphemerisToFill.commonEphemerisData);

        qzssEphemerisToFill.signalHealth = receivedQzssEphemeris.signalHealth;
        qzssEphemerisToFill.URAI = receivedQzssEphemeris.URAI;
        qzssEphemerisToFill.codeL2 = receivedQzssEphemeris.codeL2;
        qzssEphemerisToFill.dataFlagL2P = receivedQzssEphemeris.dataFlagL2P;
        qzssEphemerisToFill.tgd = receivedQzssEphemeris.tgd;
        qzssEphemerisToFill.fitInterval = receivedQzssEphemeris.fitInterval;
        qzssEphemerisToFill.IODC = receivedQzssEphemeris.IODC;
    }
}

/* convert system info to GnssDataNotification format and dispatch
   to the registered adapter */
void  LocApiV02 :: reportSystemInfo(
    const qmiLocSystemInfoIndMsgT_v02* system_info_ptr){

    if (system_info_ptr == nullptr) {
        return;
    }

    LOC_LOGe("system info type: %d, leap second valid: %d "
             "current gps time:valid:%d, week: %d, msec: %d,"
             "current leap second:valid %d, seconds %d, "
             "next gps time: valid %d, week: %d, msec: %d,"
             "next leap second: valid %d, seconds %d",
             system_info_ptr->systemInfo,
             system_info_ptr->nextLeapSecondInfo_valid,
             system_info_ptr->nextLeapSecondInfo.gpsTimeCurrent_valid,
             system_info_ptr->nextLeapSecondInfo.gpsTimeCurrent.gpsWeek,
             system_info_ptr->nextLeapSecondInfo.gpsTimeCurrent.gpsTimeOfWeekMs,
             system_info_ptr->nextLeapSecondInfo.leapSecondsCurrent_valid,
             system_info_ptr->nextLeapSecondInfo.leapSecondsCurrent,
             system_info_ptr->nextLeapSecondInfo.gpsTimeNextLsEvent_valid,
             system_info_ptr->nextLeapSecondInfo.gpsTimeNextLsEvent.gpsWeek,
             system_info_ptr->nextLeapSecondInfo.gpsTimeNextLsEvent.gpsTimeOfWeekMs,
             system_info_ptr->nextLeapSecondInfo.leapSecondsNext_valid,
             system_info_ptr->nextLeapSecondInfo.leapSecondsNext);

    LocationSystemInfo systemInfo = {};
    if ((system_info_ptr->systemInfo == eQMI_LOC_NEXT_LEAP_SECOND_INFO_V02) &&
        (system_info_ptr->nextLeapSecondInfo_valid == 1)) {

        const qmiLocNextLeapSecondInfoStructT_v02 &nextLeapSecondInfo =
            system_info_ptr->nextLeapSecondInfo;

        if (nextLeapSecondInfo.gpsTimeNextLsEvent_valid &&
                nextLeapSecondInfo.leapSecondsCurrent_valid &&
                nextLeapSecondInfo.leapSecondsNext_valid) {

            systemInfo.systemInfoMask |= LOCATION_SYS_INFO_LEAP_SECOND;
            systemInfo.leapSecondSysInfo.leapSecondInfoMask |=
                    LEAP_SECOND_SYS_INFO_LEAP_SECOND_CHANGE_BIT;

            LeapSecondChangeInfo &leapSecondChangeInfo =
                    systemInfo.leapSecondSysInfo.leapSecondChangeInfo;
            leapSecondChangeInfo.gpsTimestampLsChange.systemWeek =
                    nextLeapSecondInfo.gpsTimeNextLsEvent.gpsWeek;
            leapSecondChangeInfo.gpsTimestampLsChange.systemMsec =
                    nextLeapSecondInfo.gpsTimeNextLsEvent.gpsTimeOfWeekMs;
            leapSecondChangeInfo.gpsTimestampLsChange.validityMask =
                    (GNSS_SYSTEM_TIME_WEEK_VALID | GNSS_SYSTEM_TIME_WEEK_MS_VALID);

            leapSecondChangeInfo.leapSecondsBeforeChange =
                    nextLeapSecondInfo.leapSecondsCurrent;
            leapSecondChangeInfo.leapSecondsAfterChange =
                    nextLeapSecondInfo.leapSecondsNext;
        }

        if (nextLeapSecondInfo.leapSecondsCurrent_valid) {
            systemInfo.systemInfoMask |= LOCATION_SYS_INFO_LEAP_SECOND;
            systemInfo.leapSecondSysInfo.leapSecondInfoMask |=
                    LEAP_SECOND_SYS_INFO_CURRENT_LEAP_SECONDS_BIT;
            systemInfo.leapSecondSysInfo.leapSecondCurrent =
                    nextLeapSecondInfo.leapSecondsCurrent;
        }
    }

    if (systemInfo.systemInfoMask) {
        LocApiBase::reportLocationSystemInfo(systemInfo);
    }
}

void LocApiV02::reportLocationRequestNotification(
    const qmiLocLocationRequestNotificationIndMsgT_v02* loc_req_notif)
{
    GnssNfwNotification notification = {};

    LOC_LOGv("IN: protocolStack=%d"
             " ,clientStrId_valid=%d"
             " ,clientStrId=%s"
             " ,requestor=%d"
             " ,requestorId=%s"
             " ,responseType=%d"
             " ,inEmergencyMode=%d"
             " ,isCachedLocation=%u",
             loc_req_notif->protocolStack,
             loc_req_notif->clientStrId_valid,
             loc_req_notif->clientStrId,
             loc_req_notif->requestor,
             loc_req_notif->requestorId,
             loc_req_notif->responseType,
             loc_req_notif->inEmergencyMode,
             loc_req_notif->isCachedLocation);

    switch (loc_req_notif->protocolStack) {
    case eQMI_LOC_CTRL_PLANE_V02:
        notification.protocolStack = GNSS_NFW_CTRL_PLANE;
        break;
    case eQMI_LOC_SUPL_V02:
        notification.protocolStack = GNSS_NFW_SUPL;
        break;
    case eQMI_LOC_IMS_V02:
        notification.protocolStack = GNSS_NFW_IMS;
        break;
    case eQMI_LOC_SIM_V02:
        notification.protocolStack = GNSS_NFW_SIM;
        break;
    case eQMI_LOC_MDT_V02:
    case eQMI_LOC_TLOC_V02:
    case eQMI_LOC_OTHER_V02:
    default:
        notification.protocolStack = GNSS_NFW_OTHER_PROTOCOL_STACK;
        if (loc_req_notif->clientStrId_valid) {
            strlcpy(notification.otherProtocolStackName,
                    loc_req_notif->clientStrId,
                    sizeof(notification.otherProtocolStackName));
        } else {
            strlcpy(notification.otherProtocolStackName,
                    "NFW Client",
                    sizeof(notification.otherProtocolStackName));
        }
        break;
    }
    switch (loc_req_notif->requestor) {
    case eQMI_LOC_REQUESTOR_CARRIER_V02:
        notification.requestor = GNSS_NFW_CARRIER;
        break;
    case eQMI_LOC_REQUESTOR_OEM_V02:
        notification.requestor = GNSS_NFW_OEM;
        break;
    case eQMI_LOC_REQUESTOR_MODEM_CHIPSET_VENDOR_V02:
        notification.requestor = GNSS_NFW_MODEM_CHIPSET_VENDOR;
        break;
    case eQMI_LOC_REQUESTOR_GNSS_CHIPSET_VENDOR_V02:
        notification.requestor = GNSS_NFW_GNSS_CHIPSET_VENDOR;
        break;
    case eQMI_LOC_REQUESTOR_OTHER_CHIPSET_VENDOR_V02:
        notification.requestor = GNSS_NFW_OTHER_CHIPSET_VENDOR;
        break;
    case eQMI_LOC_REQUESTOR_AUTOMOBILE_CLIENT_V02:
        notification.requestor = GNSS_NFW_AUTOMOBILE_CLIENT;
        break;
    case eQMI_LOC_REQUESTOR_OTHER_V02:
    default:
        notification.requestor = GNSS_NFW_OTHER_REQUESTOR;
        break;
    }
    switch (loc_req_notif->responseType) {
    case eQMI_LOC_REJECTED_V02:
        notification.responseType = GNSS_NFW_REJECTED;
        break;
    case eQMI_LOC_ACCEPTED_NO_LOCATION_PROVIDED_V02:
        notification.responseType = GNSS_NFW_ACCEPTED_NO_LOCATION_PROVIDED;
        break;
    case eQMI_LOC_ACCEPTED_LOCATION_PROVIDED_V02:
        notification.responseType = GNSS_NFW_ACCEPTED_LOCATION_PROVIDED;
        break;
    }
    notification.inEmergencyMode = (bool)loc_req_notif->inEmergencyMode;
    notification.isCachedLocation = (bool)loc_req_notif->isCachedLocation;

    bool isImpossibleScenario = false;
    // we need to reject various impossible scenarios
    if (notification.inEmergencyMode) {
        if (notification.protocolStack != GNSS_NFW_CTRL_PLANE &&
            notification.protocolStack != GNSS_NFW_SUPL) {
            isImpossibleScenario = true;
            LOC_LOGe("inEmergencyMode is true, but protocolStack=%d",
                notification.protocolStack);
        }
        if (GNSS_NFW_REJECTED == notification.responseType) {
            isImpossibleScenario = true;
            LOC_LOGe("inEmergencyMode is true, but responseType is REJECTED");
        }
    } else {
        // requestorId is "" for emergency
        strlcpy(notification.requestorId,
                loc_req_notif->requestorId,
                sizeof(notification.requestorId));
        // proxyAppPackageName is "" for emergency
        strlcpy(notification.proxyAppPackageName,
                ContextBase::mGps_conf.PROXY_APP_PACKAGE_NAME,
                sizeof(notification.proxyAppPackageName));
    }

    if (!isImpossibleScenario) {
        LOC_LOGv("OUT: proxyAppPackageName=%s"
                 " ,protocolStack=%d"
                 " ,otherProtocolStackName=%s"
                 " ,requestor=%d"
                 " ,requestorId=%s"
                 " ,responseType=%d"
                 " ,inEmergencyMode=%d"
                 " ,isCachedLocation=%u",
                 notification.proxyAppPackageName,
                 notification.protocolStack,
                 notification.otherProtocolStackName,
                 notification.requestor,
                 notification.requestorId,
                 notification.responseType,
                 notification.inEmergencyMode,
                 notification.isCachedLocation);

        LocApiBase::sendNfwNotification(notification);
    }
}

/* convert engine state report to loc eng format and send the converted
   report to loc eng */
void LocApiV02 :: reportEngineState (
    const qmiLocEventEngineStateIndMsgT_v02 *engine_state_ptr)
{

  LOC_LOGV("%s:%d]: state = %d\n", __func__, __LINE__,
                 engine_state_ptr->engineState);

  struct MsgUpdateEngineState : public LocMsg {
      LocApiV02* mpLocApiV02;
      bool mEngineOn;
      inline MsgUpdateEngineState(LocApiV02* pLocApiV02, bool engineOn) :
                 LocMsg(), mpLocApiV02(pLocApiV02), mEngineOn(engineOn) {}
      inline virtual void proc() const {

          // Call registerEventMask so that if qmi mask has changed,
          // it will register the new qmi mask to the modem
          mpLocApiV02->mEngineOn = mEngineOn;
          mpLocApiV02->registerEventMask(mpLocApiV02->mMask);

          if (!mEngineOn) {
              for (auto resender : mpLocApiV02->mResenders) {
                  LOC_LOGV("%s:%d]: resend failed command.", __func__, __LINE__);
                  resender();
              }
              mpLocApiV02->mResenders.clear();
          }
      }
  };

  if (eQMI_LOC_ENGINE_STATE_ON_V02 == engine_state_ptr->engineState) {
      sendMsg(new MsgUpdateEngineState(this, true));
  }
  else if (eQMI_LOC_ENGINE_STATE_OFF_V02 == engine_state_ptr->engineState) {
      sendMsg(new MsgUpdateEngineState(this, false));
  }

}

/* convert fix session state report to loc eng format and send the converted
   report to loc eng */
void LocApiV02 :: reportFixSessionState (
    const qmiLocEventFixSessionStateIndMsgT_v02 *fix_session_state_ptr)
{
  LocGpsStatusValue status;
  LOC_LOGD("%s:%d]: state = %d\n", __func__, __LINE__,
                fix_session_state_ptr->sessionState);

  status = LOC_GPS_STATUS_NONE;
  if (fix_session_state_ptr->sessionState == eQMI_LOC_FIX_SESSION_STARTED_V02)
  {
    status = LOC_GPS_STATUS_SESSION_BEGIN;
  }
  else if (fix_session_state_ptr->sessionState
           == eQMI_LOC_FIX_SESSION_FINISHED_V02)
  {
    status = LOC_GPS_STATUS_SESSION_END;
  }
  reportStatus(status);
}

/* convert NMEA report to loc eng format and send the converted
   report to loc eng */
void LocApiV02 :: reportNmea (
  const qmiLocEventNmeaIndMsgT_v02 *nmea_report_ptr)
{
    if (NULL == nmea_report_ptr) {
        return;
    }

    const char* p_nmea = NULL;
    uint32_t q_nmea_len = 0;

    if (nmea_report_ptr->expandedNmea_valid) {
        p_nmea = nmea_report_ptr->expandedNmea;
        q_nmea_len = strlen(nmea_report_ptr->expandedNmea);
        if (q_nmea_len > QMI_LOC_EXPANDED_NMEA_STRING_MAX_LENGTH_V02) {
            q_nmea_len = QMI_LOC_EXPANDED_NMEA_STRING_MAX_LENGTH_V02;
        }
    }
    else
    {
        p_nmea = nmea_report_ptr->nmea;
        q_nmea_len = strlen(nmea_report_ptr->nmea);
        if (q_nmea_len > QMI_LOC_NMEA_STRING_MAX_LENGTH_V02) {
            q_nmea_len = QMI_LOC_NMEA_STRING_MAX_LENGTH_V02;
        }
    }

    if ((NULL != p_nmea) && (q_nmea_len > 0)) {
        LocApiBase::reportNmea(p_nmea, q_nmea_len);
    }
}

/* convert and report an ATL request to loc engine */
void LocApiV02 :: reportAtlRequest(
  const qmiLocEventLocationServerConnectionReqIndMsgT_v02 * server_request_ptr)
{
  uint32_t connHandle = server_request_ptr->connHandle;

  if (server_request_ptr->requestType == eQMI_LOC_SERVER_REQUEST_OPEN_V02)
  {
    LocAGpsType agpsType = LOC_AGPS_TYPE_ANY;
    LocApnTypeMask apnTypeMask = 0;

    switch (server_request_ptr->wwanType)
    {
      case eQMI_LOC_WWAN_TYPE_INTERNET_V02:
        agpsType = LOC_AGPS_TYPE_WWAN_ANY;
        break;
      case eQMI_LOC_WWAN_TYPE_AGNSS_V02:
        agpsType = LOC_AGPS_TYPE_SUPL;
        break;
      case eQMI_LOC_WWAN_TYPE_AGNSS_EMERGENCY_V02:
        agpsType = LOC_AGPS_TYPE_SUPL_ES;
        break;
      default:
        agpsType = LOC_AGPS_TYPE_WWAN_ANY;
        break;
    }

    if (server_request_ptr->apnTypeMask_valid) {
        apnTypeMask = convertQmiLocApnTypeMask(server_request_ptr->apnTypeMask);
    }
    LOC_LOGd("handle=%d agpsType=0x%X apnTypeMask=0x%X",
        connHandle, agpsType, apnTypeMask);
    requestATL(connHandle, agpsType, apnTypeMask);
  }
  // service the ATL close request
  else if (server_request_ptr->requestType == eQMI_LOC_SERVER_REQUEST_CLOSE_V02)
  {
    releaseATL(connHandle);
  }
}

/* conver the NI report to loc eng format and send t loc engine */
void LocApiV02 :: reportNiRequest(
    const qmiLocEventNiNotifyVerifyReqIndMsgT_v02 *ni_req_ptr)
{
    GnssNiNotification notif = {};
    notif.messageEncoding = GNSS_NI_ENCODING_TYPE_NONE ;
    notif.requestorEncoding = GNSS_NI_ENCODING_TYPE_NONE;
    notif.timeoutResponse = GNSS_NI_RESPONSE_NO_RESPONSE;
    notif.timeout = LOC_NI_NO_RESPONSE_TIME;

    /* Handle Vx request */
    if (1 == ni_req_ptr->NiVxInd_valid) {
        const qmiLocNiVxNotifyVerifyStructT_v02 *vx_req = &(ni_req_ptr->NiVxInd);

        notif.type = GNSS_NI_TYPE_VOICE;

        // Requestor ID, the requestor id recieved is NULL terminated
        hexcode(notif.requestor, sizeof notif.requestor,
                (char *)vx_req->requestorId, vx_req->requestorId_len );
    }

    /* Handle UMTS CP request*/
    else if (1 == ni_req_ptr->NiUmtsCpInd_valid) {
        const qmiLocNiUmtsCpNotifyVerifyStructT_v02 *umts_cp_req =
            &ni_req_ptr->NiUmtsCpInd;

        notif.type = GNSS_NI_TYPE_CONTROL_PLANE;

        /* notificationText should always be a NULL terminated string */
        hexcode(notif.message, sizeof notif.message,
                (char *)umts_cp_req->notificationText,
                umts_cp_req->notificationText_len);

        /* Store requestor ID */
        hexcode(notif.requestor, sizeof(notif.requestor),
                (char *)umts_cp_req->requestorId.codedString,
                umts_cp_req->requestorId.codedString_len);

        /* convert encodings */
        notif.messageEncoding = convertNiEncoding(umts_cp_req->dataCodingScheme);

        notif.requestorEncoding =
            convertNiEncoding(umts_cp_req->requestorId.dataCodingScheme);

        /* LCS address (using extras field) */
        if (0 != umts_cp_req->clientAddress_len) {
            char lcs_addr[32]; // Decoded LCS address for UMTS CP NI

            // Copy LCS Address into notif.extras in the format: Address = 012345
            strlcat(notif.extras, LOC_NI_NOTIF_KEY_ADDRESS, sizeof (notif.extras));
            strlcat(notif.extras, " = ", sizeof notif.extras);
            int addr_len = 0;
            const char *address_source = NULL;
            address_source = (char *)umts_cp_req->clientAddress;
            // client Address is always NULL terminated
            addr_len = decodeAddress(lcs_addr, sizeof(lcs_addr), address_source,
                                     umts_cp_req->clientAddress_len);

            // The address is ASCII string
            if (addr_len) {
                strlcat(notif.extras, lcs_addr, sizeof notif.extras);
            }
        }
    } else if (1 == ni_req_ptr->NiSuplInd_valid) {
        const qmiLocNiSuplNotifyVerifyStructT_v02 *supl_req =
            &ni_req_ptr->NiSuplInd;

        notif.type = GNSS_NI_TYPE_SUPL;

        // Client name
        if (supl_req->valid_flags & QMI_LOC_SUPL_CLIENT_NAME_MASK_V02) {
            hexcode(notif.message, sizeof(notif.message),
                    (char *)supl_req->clientName.formattedString,
                    supl_req->clientName.formattedString_len);
            LOC_LOGv("SUPL NI: client_name: %s \n", notif.message);
        } else {
            LOC_LOGv("SUPL NI: client_name not present.");
        }

        // Requestor ID
        if (supl_req->valid_flags & QMI_LOC_SUPL_REQUESTOR_ID_MASK_V02) {
            hexcode(notif.requestor, sizeof notif.requestor,
                    (char*)supl_req->requestorId.formattedString,
                    supl_req->requestorId.formattedString_len);

            LOC_LOGv("SUPL NI: requestor: %s", notif.requestor);
        } else {
            LOC_LOGv("SUPL NI: requestor not present.");
        }

        // Encoding type
        if (supl_req->valid_flags & QMI_LOC_SUPL_DATA_CODING_SCHEME_MASK_V02) {
            notif.messageEncoding = convertNiEncoding(supl_req->dataCodingScheme);
            notif.requestorEncoding = convertNiEncoding(supl_req->dataCodingScheme);
        } else {
            notif.messageEncoding = notif.requestorEncoding = GNSS_NI_ENCODING_TYPE_NONE;
        }

        // ES SUPL
        if (1 == ni_req_ptr->suplEmergencyNotification_valid) {
            const qmiLocEmergencyNotificationStructT_v02 *supl_emergency_request =
                &ni_req_ptr->suplEmergencyNotification;

            notif.type = GNSS_NI_TYPE_EMERGENCY_SUPL;
        }
    } //ni_req_ptr->NiSuplInd_valid == 1
    else {
        LOC_LOGe("unknown request event");
        return;
    }

    // Set default_response & notify_flags
    convertNiNotifyVerifyType(&notif, ni_req_ptr->notificationType);

    qmiLocEventNiNotifyVerifyReqIndMsgT_v02 *ni_req_copy_ptr =
        (qmiLocEventNiNotifyVerifyReqIndMsgT_v02 *)malloc(sizeof(*ni_req_copy_ptr));

    LocInEmergency emergencyState = ni_req_ptr->isInEmergencySession_valid ?
            (ni_req_ptr->isInEmergencySession ? LOC_IN_EMERGENCY_SET : LOC_IN_EMERGENCY_NOT_SET) :
            LOC_IN_EMERGENCY_UNKNOWN;
    if (NULL != ni_req_copy_ptr) {
        memcpy(ni_req_copy_ptr, ni_req_ptr, sizeof(*ni_req_copy_ptr));
        requestNiNotify(notif, (const void*)ni_req_copy_ptr, emergencyState);
    } else {
        LOC_LOGe("Error copying NI request");
    }
}

/* If Confidence value is less than 68%, then scale the accuracy value to
   68%.confidence.*/
void LocApiV02 :: scaleAccuracyTo68PercentConfidence(
                                                const uint8_t confidenceValue,
                                                LocGpsLocation &gpsLocation,
                                                const bool isCircularUnc)
{
  if (confidenceValue < 68)
  {
    // Circular uncertainty is at 63%.confidence. Scale factor should be
    // 1.072(from 63% -> 68%)
    uint8_t realConfidence = (isCircularUnc) ? 63:confidenceValue;
    // get scaling value based on 2D% confidence scaling table
    for (uint8_t iter = 0; iter < CONF_SCALER_ARRAY_MAX; iter++)
    {
      if (realConfidence <= confScalers[iter].confidence)
      {
        LOC_LOGD("Confidence: %d, Scaler value:%f",
                realConfidence,confScalers[iter].scaler_to_68);
        gpsLocation.accuracy *= confScalers[iter].scaler_to_68;
        break;
      }
    }
  }
}

/* Report the Xtra Server Url from the modem to HAL*/
void LocApiV02 :: reportXtraServerUrl(
                const qmiLocEventInjectPredictedOrbitsReqIndMsgT_v02*
                server_request_ptr)
{

  if (server_request_ptr->serverList.serverList_len == 1)
  {
    reportXtraServer(server_request_ptr->serverList.serverList[0].serverUrl,
                     "",
                     "",
                     QMI_LOC_MAX_SERVER_ADDR_LENGTH_V02);
  }
  else if (server_request_ptr->serverList.serverList_len == 2)
  {
    reportXtraServer(server_request_ptr->serverList.serverList[0].serverUrl,
                     server_request_ptr->serverList.serverList[1].serverUrl,
                     "",
                     QMI_LOC_MAX_SERVER_ADDR_LENGTH_V02);
  }
  else
  {
    reportXtraServer(server_request_ptr->serverList.serverList[0].serverUrl,
                     server_request_ptr->serverList.serverList[1].serverUrl,
                     server_request_ptr->serverList.serverList[2].serverUrl,
                     QMI_LOC_MAX_SERVER_ADDR_LENGTH_V02);
  }

}

/* convert Ni Encoding type from QMI_LOC to loc eng format */
GnssNiEncodingType LocApiV02 ::convertNiEncoding(
  qmiLocNiDataCodingSchemeEnumT_v02 loc_encoding)
{
   GnssNiEncodingType enc = GNSS_NI_ENCODING_TYPE_NONE;

   switch (loc_encoding)
   {
     case eQMI_LOC_NI_SUPL_UTF8_V02:
       enc = GNSS_NI_ENCODING_TYPE_UTF8;
       break;
     case eQMI_LOC_NI_SUPL_UCS2_V02:
       enc = GNSS_NI_ENCODING_TYPE_UCS2;
       break;
     case eQMI_LOC_NI_SUPL_GSM_DEFAULT_V02:
       enc = GNSS_NI_ENCODING_TYPE_GSM_DEFAULT;
       break;
     case eQMI_LOC_NI_SS_LANGUAGE_UNSPEC_V02:
       enc = GNSS_NI_ENCODING_TYPE_GSM_DEFAULT; // SS_LANGUAGE_UNSPEC = GSM
       break;
     default:
       break;
   }

   return enc;
}

/*convert NI notify verify type from QMI LOC to loc eng format*/
bool LocApiV02 :: convertNiNotifyVerifyType (
  GnssNiNotification *notif,
  qmiLocNiNotifyVerifyEnumT_v02 notif_priv)
{
  switch (notif_priv)
   {
   case eQMI_LOC_NI_USER_NO_NOTIFY_NO_VERIFY_V02:
      notif->options = 0;
      break;

   case eQMI_LOC_NI_USER_NOTIFY_ONLY_V02:
      notif->options = GNSS_NI_OPTIONS_NOTIFICATION_BIT;
      break;

   case eQMI_LOC_NI_USER_NOTIFY_VERIFY_ALLOW_NO_RESP_V02:
      notif->options = GNSS_NI_OPTIONS_NOTIFICATION_BIT | GNSS_NI_OPTIONS_VERIFICATION_BIT;
      notif->timeoutResponse = GNSS_NI_RESPONSE_ACCEPT;
      break;

   case eQMI_LOC_NI_USER_NOTIFY_VERIFY_NOT_ALLOW_NO_RESP_V02:
      notif->options = GNSS_NI_OPTIONS_NOTIFICATION_BIT | GNSS_NI_OPTIONS_VERIFICATION_BIT;
      notif->timeoutResponse = GNSS_NI_RESPONSE_DENY;
      break;

   case eQMI_LOC_NI_USER_NOTIFY_VERIFY_PRIVACY_OVERRIDE_V02:
      notif->options = GNSS_NI_OPTIONS_PRIVACY_OVERRIDE_BIT;
      break;

   default:
      return false;
   }

   return true;
}

/* convert and report GNSS measurement data to loc eng */
void LocApiV02::reportGnssMeasurementData(
  const qmiLocEventGnssSvMeasInfoIndMsgT_v02& gnss_measurement_report_ptr)
{
    LOC_LOGv("entering");

    static uint32_t prevRefFCount = 0;
    static bool newMeasProcessed = false;
    uint8_t maxSubSeqNum = 0;
    uint8_t subSeqNum = 0;

    if (gnss_measurement_report_ptr.maxSubSeqNum_valid &&
        gnss_measurement_report_ptr.subSeqNum_valid) {
        maxSubSeqNum = gnss_measurement_report_ptr.maxSubSeqNum;
        subSeqNum = gnss_measurement_report_ptr.subSeqNum;
    } else {
        maxSubSeqNum = 0;
        subSeqNum = 0;
    }

    LOC_LOGd("[SvMeas] nHz (%d, %d), SeqNum: %d, MaxMsgNum: %d, "
             "SubSeqNum: %d, MaxSubMsgNum: %d, "
             "SvSystem: %d SignalType: %" PRIu64 " MeasValid: %d, #of SV: %d",
             gnss_measurement_report_ptr.nHzMeasurement_valid,
             gnss_measurement_report_ptr.nHzMeasurement,
             gnss_measurement_report_ptr.seqNum,
             gnss_measurement_report_ptr.maxMessageNum,
             subSeqNum,
             maxSubSeqNum,
             gnss_measurement_report_ptr.system,
             gnss_measurement_report_ptr.gnssSignalType,
             gnss_measurement_report_ptr.svMeasurement_valid,
             gnss_measurement_report_ptr.svMeasurement_len);

    if (!mGnssMeasurements) {
        mGnssMeasurements = (GnssMeasurements*)malloc(sizeof(GnssMeasurements));
        if (!mGnssMeasurements) {
            LOC_LOGe("Malloc failed to allocate heap memory for mGnssMeasurements");
            return;
        }
        resetSvMeasurementReport();
        newMeasProcessed = false;
    }

    if (gnss_measurement_report_ptr.seqNum > gnss_measurement_report_ptr.maxMessageNum ||
        subSeqNum > maxSubSeqNum) {
        LOC_LOGe("Invalid seqNum or subSeqNum, do not proceed");
        return;
    }

    // in case the measurement with seqNum of 1 is dropped, we will use ref count
    // to reset the measurement
    if ((gnss_measurement_report_ptr.seqNum == 1 && subSeqNum <= 1) ||
        (gnss_measurement_report_ptr.systemTimeExt_valid &&
         gnss_measurement_report_ptr.systemTimeExt.refFCount != prevRefFCount)) {
        // we have received some valid info since we last reported when
        // seq num matches with max seq num
        if (true == newMeasProcessed) {
            LOC_LOGe ("report due to seq number jump");
            reportSvMeasurementInternal();
            resetSvMeasurementReport();
            newMeasProcessed = false;
        }

        mHlosQtimer1 = getQTimerTickCount();
        mRefFCount = gnss_measurement_report_ptr.systemTimeExt.refFCount;
        LOC_LOGv("mHlosQtimer1=%" PRIi64 " mRefFCount=%d", mHlosQtimer1, mRefFCount);
        prevRefFCount = gnss_measurement_report_ptr.systemTimeExt.refFCount;
        if (gnss_measurement_report_ptr.nHzMeasurement_valid &&
            gnss_measurement_report_ptr.nHzMeasurement) {
            mGnssMeasurements->gnssSvMeasurementSet.isNhz = true;
        }
        mCounter++;
    }

    Gnss_LocSvSystemEnumType locSvSystemType =
        getLocApiSvSystemType(gnss_measurement_report_ptr.system);
    if (GNSS_LOC_SV_SYSTEM_UNKNOWN == locSvSystemType) {
        LOC_LOGi("Unknown sv system");
        return;
    }

    // set up indication that we have processed some new measurement
    newMeasProcessed = true;

    if (subSeqNum <= 1) {
        convertGnssMeasurementsHeader(locSvSystemType, gnss_measurement_report_ptr);
    }

    // check whether we have valid dgnss measurement
    bool validDgnssMeas = false;
    if ((gnss_measurement_report_ptr.dgnssSvMeasurement_valid) &&
        (gnss_measurement_report_ptr.dgnssSvMeasurement_len != 0)){
        uint32_t totalSvMeasLen = 0;
        if (gnss_measurement_report_ptr.svMeasurement_valid) {
            totalSvMeasLen = gnss_measurement_report_ptr.svMeasurement_len;
            if (gnss_measurement_report_ptr.extSvMeasurement_valid) {
                totalSvMeasLen += gnss_measurement_report_ptr.extSvMeasurement_len;
            }
        }
        if (totalSvMeasLen == gnss_measurement_report_ptr.dgnssSvMeasurement_len) {
            validDgnssMeas = true;
        }
    }

    // number of measurements
    if (gnss_measurement_report_ptr.svMeasurement_valid) {
        if (gnss_measurement_report_ptr.svMeasurement_len != 0 &&
            gnss_measurement_report_ptr.svMeasurement_len <= QMI_LOC_SV_MEAS_LIST_MAX_SIZE_V02) {
            // the array of measurements
            LOC_LOGv("Measurements received for GNSS system %d",
                     gnss_measurement_report_ptr.system);

            if (0 == mGnssMeasurements->gnssMeasNotification.count) {
                mAgcIsPresent = true;
            }
            for (uint32_t index = 0; index < gnss_measurement_report_ptr.svMeasurement_len &&
                    mGnssMeasurements->gnssMeasNotification.count < GNSS_MEASUREMENTS_MAX;
                    index++) {
                LOC_LOGv("index=%u count=%" PRIu32,
                    index, mGnssMeasurements->gnssMeasNotification.count);
                if ((gnss_measurement_report_ptr.svMeasurement[index].validMeasStatusMask &
                     QMI_LOC_MASK_MEAS_STATUS_GNSS_FRESH_MEAS_STAT_BIT_VALID_V02) &&
                    (gnss_measurement_report_ptr.svMeasurement[index].measurementStatus &
                     QMI_LOC_MASK_MEAS_STATUS_GNSS_FRESH_MEAS_VALID_V02)) {
                    mAgcIsPresent &= convertGnssMeasurements(
                        gnss_measurement_report_ptr,
                        index, false, validDgnssMeas);
                    mGnssMeasurements->gnssMeasNotification.count++;
                } else {
                    LOC_LOGv("Measurements are stale, do not report");
                }
            }
            LOC_LOGv("there are %d SV measurements now, total=%" PRIu32,
                     gnss_measurement_report_ptr.svMeasurement_len,
                     mGnssMeasurements->gnssMeasNotification.count);

            /* now check if more measurements are available (some constellations such
            as BDS have more measurements available in extSvMeasurement)
            */
            if (gnss_measurement_report_ptr.extSvMeasurement_valid &&
                gnss_measurement_report_ptr.extSvMeasurement_len != 0 &&
                gnss_measurement_report_ptr.extSvMeasurement_len <=
                    QMI_LOC_EXT_SV_MEAS_LIST_MAX_SIZE_V02) {
                // the array of measurements
                LOC_LOGv("More measurements received for GNSS system %d",
                         gnss_measurement_report_ptr.system);
                for (uint32_t index = 0; index < gnss_measurement_report_ptr.extSvMeasurement_len &&
                        mGnssMeasurements->gnssMeasNotification.count < GNSS_MEASUREMENTS_MAX;
                        index++) {
                    LOC_LOGv("index=%u count=%" PRIu32, index, mGnssMeasurements->gnssMeasNotification.count);
                    if ((gnss_measurement_report_ptr.extSvMeasurement[index].validMeasStatusMask &
                         QMI_LOC_MASK_MEAS_STATUS_GNSS_FRESH_MEAS_STAT_BIT_VALID_V02) &&
                        (gnss_measurement_report_ptr.extSvMeasurement[index].measurementStatus &
                         QMI_LOC_MASK_MEAS_STATUS_GNSS_FRESH_MEAS_VALID_V02)) {
                        mAgcIsPresent &= convertGnssMeasurements(
                            gnss_measurement_report_ptr,
                            index, true, validDgnssMeas);
                        mGnssMeasurements->gnssMeasNotification.count++;
                    }
                    else {
                        LOC_LOGv("Measurements are stale, do not report");
                    }
                }
                LOC_LOGv("there are %d SV measurements now, total=%" PRIu32,
                         gnss_measurement_report_ptr.extSvMeasurement_len,
                         mGnssMeasurements->gnssMeasNotification.count);
            }
        }
    } else {
        LOC_LOGv("there is no valid GNSS measurement for system %d, total=%" PRIu32,
                 gnss_measurement_report_ptr.system,
            mGnssMeasurements->gnssMeasNotification.count);
    }
    // the GPS clock time reading
    if (eQMI_LOC_SV_SYSTEM_GPS_V02 == gnss_measurement_report_ptr.system &&
        subSeqNum <= 1 &&
        false == mGPSreceived) {
        mGPSreceived = true;
        mMsInWeek = convertGnssClock(mGnssMeasurements->gnssMeasNotification.clock,
                                     gnss_measurement_report_ptr);
    }

    if (gnss_measurement_report_ptr.maxMessageNum == gnss_measurement_report_ptr.seqNum &&
        maxSubSeqNum == subSeqNum) {
        LOC_LOGD("Report the measurements to the upper layer");
        int64_t elapsedRealTime = -1;
        int64_t unc;
        if (gnss_measurement_report_ptr.refCountTicks_valid &&
            gnss_measurement_report_ptr.refCountTicksUnc_valid) {
            /* deal with Qtimer for ElapsedRealTimeNanos */
            mGnssMeasurements->gnssMeasNotification.clock.flags |=
                    GNSS_MEASUREMENTS_CLOCK_FLAGS_ELAPSED_REAL_TIME_BIT;

            elapsedRealTime = ElapsedRealtimeEstimator::getElapsedRealtimeQtimer(
                    gnss_measurement_report_ptr.refCountTicks);

            /* Uncertainty on HLOS time is 0, so the uncertainty of the difference
            is the uncertainty of the Qtimer in the modem
            Note that gnss_measurement_report_ptr.refCountTicksUncis in msec */
            unc = gnss_measurement_report_ptr.refCountTicksUnc * 1000000;
        } else {
            //If Qtimer isn't valid, estimate the elapsedRealTime
            GnssMeasurementsNotification& in = mGnssMeasurements->gnssMeasNotification;
            const uint32_t UTC_TO_GPS_SECONDS = 315964800;
            int64_t measTimeNanos = (int64_t)in.clock.timeNs - (int64_t)in.clock.fullBiasNs
                    - (int64_t)in.clock.biasNs - (int64_t)in.clock.leapSecond * 1000000000
                    + (int64_t)UTC_TO_GPS_SECONDS * 1000000000;
            bool isCurDataTimeTrustable =
                    in.clock.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_LEAP_SECOND_BIT &&
                    in.clock.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_FULL_BIAS_BIT &&
                    in.clock.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_BIAS_BIT &&
                    in.clock.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_BIAS_UNCERTAINTY_BIT;
            elapsedRealTime = mMeasElapsedRealTimeCal.
                    getElapsedRealtimeEstimateNanos(measTimeNanos, isCurDataTimeTrustable, 0);
            unc = mMeasElapsedRealTimeCal.getElapsedRealtimeUncNanos();
        }

        if (elapsedRealTime != -1) {
            mGnssMeasurements->gnssMeasNotification.clock.flags |=
                    GNSS_MEASUREMENTS_CLOCK_FLAGS_ELAPSED_REAL_TIME_BIT;
            mGnssMeasurements->gnssMeasNotification.clock.elapsedRealTime = elapsedRealTime;
            mGnssMeasurements->gnssMeasNotification.clock.elapsedRealTimeUnc = unc;
        }
        LOC_LOGd("Measurement elapsedRealtime: %" PRIi64 " uncertainty: %" PRIi64 "",
               mGnssMeasurements->gnssMeasNotification.clock.elapsedRealTime,
               mGnssMeasurements->gnssMeasNotification.clock.elapsedRealTimeUnc);

        reportSvMeasurementInternal();
        resetSvMeasurementReport();
        // set up flag to indicate that no new info in mGnssMeasurements
        newMeasProcessed = false;
    }
}

void LocApiV02::setGnssBiases() {
    GnssMeasurementsData* measData;
    uint64_t tempFlag, tempFlagUnc;

    for (uint32_t i = 0; i < mGnssMeasurements->gnssMeasNotification.count; i++) {
        measData = &mGnssMeasurements->gnssMeasNotification.measurements[i];
        switch (measData->gnssSignalType) {
        case GNSS_SIGNAL_GPS_L1CA:
            measData->fullInterSignalBiasNs = 0.0;
            measData->flags |= GNSS_MEASUREMENTS_DATA_FULL_ISB_BIT;
            measData->fullInterSignalBiasUncertaintyNs = 0.0;
            measData->flags |= GNSS_MEASUREMENTS_DATA_FULL_ISB_UNCERTAINTY_BIT;
            break;

        case GNSS_SIGNAL_GPS_L5:
        case GNSS_SIGNAL_QZSS_L5:
            if (mTimeBiases.flags & BIAS_GPSL1_GPSL5_VALID) {
                measData->fullInterSignalBiasNs = -mTimeBiases.gpsL1_gpsL5;
                measData->flags |= GNSS_MEASUREMENTS_DATA_FULL_ISB_BIT;
            }
            if (mTimeBiases.flags & BIAS_GPSL1_GPSL5_UNC_VALID) {
                measData->fullInterSignalBiasUncertaintyNs = mTimeBiases.gpsL1_gpsL5Unc;
                measData->flags |= GNSS_MEASUREMENTS_DATA_FULL_ISB_UNCERTAINTY_BIT;
            }
            break;

        case GNSS_SIGNAL_GLONASS_G1:
            if (mTimeBiases.flags & BIAS_GPSL1_GLOG1_VALID) {
                measData->fullInterSignalBiasNs = -mTimeBiases.gpsL1_gloG1;
                measData->flags |= GNSS_MEASUREMENTS_DATA_FULL_ISB_BIT;
            }
            if (mTimeBiases.flags & BIAS_GPSL1_GLOG1_UNC_VALID) {
                measData->fullInterSignalBiasUncertaintyNs = mTimeBiases.gpsL1_gloG1Unc;
                measData->flags |= GNSS_MEASUREMENTS_DATA_FULL_ISB_UNCERTAINTY_BIT;
            }
            break;

        case GNSS_SIGNAL_GALILEO_E1:
            if (mTimeBiases.flags & BIAS_GPSL1_GALE1_VALID) {
                measData->fullInterSignalBiasNs = -mTimeBiases.gpsL1_galE1;
                measData->flags |= GNSS_MEASUREMENTS_DATA_FULL_ISB_BIT;
            }
            if (mTimeBiases.flags & BIAS_GPSL1_GALE1_UNC_VALID) {
                measData->fullInterSignalBiasUncertaintyNs = mTimeBiases.gpsL1_galE1Unc;
                measData->flags |= GNSS_MEASUREMENTS_DATA_FULL_ISB_UNCERTAINTY_BIT;
            }
            break;

        case GNSS_SIGNAL_GALILEO_E5A:
            tempFlag = BIAS_GPSL1_VALID | BIAS_GALE1_VALID | BIAS_GALE1_GALE5A_VALID;
            tempFlagUnc =
                    BIAS_GPSL1_UNC_VALID | BIAS_GALE1_UNC_VALID | BIAS_GALE1_GALE5A_UNC_VALID;
            if (tempFlag == (mTimeBiases.flags & tempFlag)) {
                measData->fullInterSignalBiasNs =
                        -mTimeBiases.gpsL1 + mTimeBiases.galE1 - mTimeBiases.galE1_galE5a;
                measData->flags |= GNSS_MEASUREMENTS_DATA_FULL_ISB_BIT;
            }
            if (tempFlagUnc == (mTimeBiases.flags & tempFlagUnc)) {
                measData->fullInterSignalBiasUncertaintyNs =
                        mTimeBiases.gpsL1Unc + mTimeBiases.galE1Unc + mTimeBiases.galE1_galE5aUnc;
                measData->flags |= GNSS_MEASUREMENTS_DATA_FULL_ISB_UNCERTAINTY_BIT;
            }
            break;

        case GNSS_SIGNAL_BEIDOU_B1I:
            if (mTimeBiases.flags & BIAS_GPSL1_BDSB1_VALID) {
                measData->fullInterSignalBiasNs = -mTimeBiases.gpsL1_bdsB1;
                measData->flags |= GNSS_MEASUREMENTS_DATA_FULL_ISB_BIT;
            }
            if (mTimeBiases.flags & BIAS_GPSL1_BDSB1_UNC_VALID) {
                measData->fullInterSignalBiasUncertaintyNs = mTimeBiases.gpsL1_bdsB1Unc;
                measData->flags |= GNSS_MEASUREMENTS_DATA_FULL_ISB_UNCERTAINTY_BIT;
            }
            break;

        case GNSS_SIGNAL_QZSS_L1CA:
        case GNSS_SIGNAL_QZSS_L1S:
        case GNSS_SIGNAL_SBAS_L1:
            if (mTimeBiases.flags & BIAS_GPSL1_VALID) {
                measData->fullInterSignalBiasNs = 0;
                measData->flags |= GNSS_MEASUREMENTS_DATA_FULL_ISB_BIT;
            }
            if (mTimeBiases.flags & BIAS_GPSL1_UNC_VALID) {
                measData->fullInterSignalBiasUncertaintyNs = 0;
                measData->flags |= GNSS_MEASUREMENTS_DATA_FULL_ISB_UNCERTAINTY_BIT;
            }
            break;

        case GNSS_SIGNAL_BEIDOU_B1C:
            tempFlag = BIAS_GPSL1_VALID | BIAS_BDSB1_VALID | BIAS_BDSB1_BDSB1C_VALID;
            tempFlagUnc =
                    BIAS_GPSL1_UNC_VALID | BIAS_BDSB1_UNC_VALID | BIAS_BDSB1_BDSB1C_UNC_VALID;
            if (tempFlag == (mTimeBiases.flags & tempFlag)) {
                measData->fullInterSignalBiasNs =
                        -mTimeBiases.gpsL1 + mTimeBiases.bdsB1 - mTimeBiases.bdsB1_bdsB1c;
                measData->flags |= GNSS_MEASUREMENTS_DATA_FULL_ISB_BIT;
            }
            if (tempFlagUnc == (mTimeBiases.flags & tempFlagUnc)) {
                measData->fullInterSignalBiasUncertaintyNs =
                        mTimeBiases.gpsL1Unc + mTimeBiases.bdsB1Unc + mTimeBiases.bdsB1_bdsB1cUnc;
                measData->flags |= GNSS_MEASUREMENTS_DATA_FULL_ISB_UNCERTAINTY_BIT;
            }
            break;

        case GNSS_SIGNAL_NAVIC_L5:
            if (mTimeBiases.flags & BIAS_GPSL1_NAVIC_VALID) {
                measData->fullInterSignalBiasNs = -mTimeBiases.gpsL1_navic;
                measData->flags |= GNSS_MEASUREMENTS_DATA_FULL_ISB_BIT;
            }
            if (mTimeBiases.flags & BIAS_GPSL1_NAVIC_UNC_VALID) {
                measData->fullInterSignalBiasUncertaintyNs = mTimeBiases.gpsL1_navicUnc;
                measData->flags |= GNSS_MEASUREMENTS_DATA_FULL_ISB_UNCERTAINTY_BIT;
            }
            break;

        case GNSS_SIGNAL_BEIDOU_B2AQ:
            tempFlag = BIAS_GPSL1_VALID | BIAS_BDSB1_VALID | BIAS_BDSB1_BDSB2A_VALID;
            tempFlagUnc =
                    BIAS_GPSL1_UNC_VALID | BIAS_BDSB1_UNC_VALID | BIAS_BDSB1_BDSB2A_UNC_VALID;
            if (tempFlag == (mTimeBiases.flags & tempFlag)) {
                measData->fullInterSignalBiasNs =
                        -mTimeBiases.gpsL1 + mTimeBiases.bdsB1 - mTimeBiases.bdsB1_bdsB2a;
                measData->flags |= GNSS_MEASUREMENTS_DATA_FULL_ISB_BIT;
            }
            if (tempFlagUnc == (mTimeBiases.flags & tempFlagUnc)) {
                measData->fullInterSignalBiasUncertaintyNs =
                        mTimeBiases.gpsL1Unc + mTimeBiases.bdsB1Unc + mTimeBiases.bdsB1_bdsB2aUnc;
                measData->flags |= GNSS_MEASUREMENTS_DATA_FULL_ISB_UNCERTAINTY_BIT;
            }
            break;

        /* not supported */
        case GNSS_SIGNAL_GPS_L1C:
        case GNSS_SIGNAL_GPS_L2:
        case GNSS_SIGNAL_GLONASS_G2:
        case GNSS_SIGNAL_GALILEO_E5B:
        case GNSS_SIGNAL_QZSS_L2:
        case GNSS_SIGNAL_BEIDOU_B2I:
        case GNSS_SIGNAL_BEIDOU_B2AI:
        default:
            break;
        }
    }
}

void LocApiV02 ::reportSvMeasurementInternal() {

    if (mGnssMeasurements) {
        // calling the base
        if (mAgcIsPresent) {
            /* If we can get AGC from QMI LOC there is no need to get it from NMEA */
            mMsInWeek = -1;
        }
        // now remove all the elements in the vector which are not for current epoch
        if (mADRdata.size() > 0) {
            auto front = mADRdata.begin();
            for (auto back = mADRdata.end(); front != back;) {
                if (mCounter != front->counter) {
                    --back;
                    swap(*front, *back);
                } else {
                    front++;
                }
            }
            if (front != mADRdata.end()) {
                mADRdata.erase(front, mADRdata.end());
            }
        }

        mGnssMeasurements->gnssSvMeasurementSet.svMeasCount = mGnssMeasurements->gnssMeasNotification.count;
        GnssSvMeasurementHeader &svMeasSetHead =
            mGnssMeasurements->gnssSvMeasurementSet.svMeasSetHeader;

        // when we received the last sequence, timestamp the packet with AP time
        struct timespec apTimestamp;
        if (clock_gettime(CLOCK_BOOTTIME, &apTimestamp)== 0) {
            svMeasSetHead.apBootTimeStamp.apTimeStamp.tv_sec = apTimestamp.tv_sec;
            svMeasSetHead.apBootTimeStamp.apTimeStamp.tv_nsec = apTimestamp.tv_nsec;

            // use the time uncertainty configured in gps.conf
            svMeasSetHead.apBootTimeStamp.apTimeStampUncertaintyMs =
                    (float)ap_timestamp_uncertainty;
            svMeasSetHead.flags |= GNSS_SV_MEAS_HEADER_HAS_AP_TIMESTAMP;

            LOC_LOGD("%s:%d QMI_MeasPacketTime  %u (sec)  %u (nsec)",__func__,__LINE__,
                     svMeasSetHead.apBootTimeStamp.apTimeStamp.tv_sec,
                     svMeasSetHead.apBootTimeStamp.apTimeStamp.tv_nsec);
        }
        else {
            svMeasSetHead.apBootTimeStamp.apTimeStampUncertaintyMs = FLT_MAX;
            LOC_LOGE("%s:%d Error in clock_gettime() ",__func__, __LINE__);
        }

        setGnssBiases();
        LOC_LOGd("report %d sv in sv meas",
                 mGnssMeasurements->gnssMeasNotification.count);

        for (uint32_t i = 0; i < mGnssMeasurements->gnssMeasNotification.count; i++) {
           LOC_LOGv("measurements[%d].flags=0x%08x "
                    "measurements[%d].gnssSignalType=%d "
                    "measurements[%d].fullInterSignalBiasNs=%.2f "
                    "measurements[%d].fullInterSignalBiasUncertaintyNs=%.2f",
                    i, mGnssMeasurements->gnssMeasNotification.measurements[i].flags,
                    i, mGnssMeasurements->gnssMeasNotification.measurements[i].gnssSignalType,
                    i, mGnssMeasurements->gnssMeasNotification.
                            measurements[i].fullInterSignalBiasNs,
                    i, mGnssMeasurements->gnssMeasNotification.
                            measurements[i].fullInterSignalBiasUncertaintyNs);
        }
        LocApiBase::reportGnssMeasurements(*mGnssMeasurements, mMsInWeek);
    }
}

void LocApiV02::convertGnssMeasurementsHeader(const Gnss_LocSvSystemEnumType locSvSystemType,
    const qmiLocEventGnssSvMeasInfoIndMsgT_v02& gnss_measurement_info)
{
    GnssSvMeasurementHeader &svMeasSetHead =
        mGnssMeasurements->gnssSvMeasurementSet.svMeasSetHeader;

    // The refCountTicks for each constellation sent for one meas report is the same
    // always. It does not matter if it gets overwritten.
    if (gnss_measurement_info.refCountTicks_valid) {
        svMeasSetHead.flags |= GNSS_SV_MEAS_HEADER_HAS_REF_COUNT_TICKS;
        svMeasSetHead.refCountTicks = gnss_measurement_info.refCountTicks;
    }

    // clock frequency
    if (1 == gnss_measurement_info.rcvrClockFrequencyInfo_valid) {
        const qmiLocRcvrClockFrequencyInfoStructT_v02* rcvClockFreqInfo =
            &gnss_measurement_info.rcvrClockFrequencyInfo;

        svMeasSetHead.clockFreq.size = sizeof(Gnss_LocRcvrClockFrequencyInfoStructType);
        svMeasSetHead.clockFreq.clockDrift =
            gnss_measurement_info.rcvrClockFrequencyInfo.clockDrift;
        svMeasSetHead.clockFreq.clockDriftUnc =
            gnss_measurement_info.rcvrClockFrequencyInfo.clockDriftUnc;
        svMeasSetHead.clockFreq.sourceOfFreq = (Gnss_LocSourceofFreqEnumType)
            gnss_measurement_info.rcvrClockFrequencyInfo.sourceOfFreq;

        svMeasSetHead.flags |= GNSS_SV_MEAS_HEADER_HAS_CLOCK_FREQ;
        LOC_LOGv("FreqInfo:: Drift: %f, DriftUnc: %f, sourceoffreq: %d",
            svMeasSetHead.clockFreq.clockDrift, svMeasSetHead.clockFreq.clockDriftUnc,
            svMeasSetHead.clockFreq.sourceOfFreq);
    }

    if ((1 == gnss_measurement_info.leapSecondInfo_valid) &&
        (0 == gnss_measurement_info.leapSecondInfo.leapSecUnc)) {

        qmiLocLeapSecondInfoStructT_v02* leapSecond =
            (qmiLocLeapSecondInfoStructT_v02*)&gnss_measurement_info.leapSecondInfo;

        svMeasSetHead.leapSec.size = sizeof(Gnss_LeapSecondInfoStructType);
        svMeasSetHead.leapSec.leapSec = gnss_measurement_info.leapSecondInfo.leapSec;
        svMeasSetHead.leapSec.leapSecUnc = gnss_measurement_info.leapSecondInfo.leapSecUnc;

        svMeasSetHead.flags |= GNSS_SV_MEAS_HEADER_HAS_LEAP_SECOND;
        LOC_LOGV("leapSecondInfo:: leapSec: %d, leapSecUnc: %d",
            svMeasSetHead.leapSec.leapSec, svMeasSetHead.leapSec.leapSecUnc);
    }

    if (1 == gnss_measurement_info.gpsGloInterSystemBias_valid) {
        qmiLocInterSystemBiasStructT_v02* interSystemBias =
            (qmiLocInterSystemBiasStructT_v02*)&gnss_measurement_info.gpsGloInterSystemBias;

        getInterSystemTimeBias("gpsGloInterSystemBias",
            svMeasSetHead.gpsGloInterSystemBias, interSystemBias);
        svMeasSetHead.flags |= GNSS_SV_MEAS_HEADER_HAS_GPS_GLO_INTER_SYSTEM_BIAS;

        if (gnss_measurement_info.gpsGloInterSystemBias.validMask &
            QMI_LOC_SYS_TIME_BIAS_VALID_V02) {
            mTimeBiases.gpsL1_gloG1 =
                    -gnss_measurement_info.gpsGloInterSystemBias.timeBias * 1000000;
            mTimeBiases.flags |= BIAS_GPSL1_GLOG1_VALID;
        }
        if (gnss_measurement_info.gpsGloInterSystemBias.validMask &
            QMI_LOC_SYS_TIME_BIAS_UNC_VALID_V02) {
            mTimeBiases.gpsL1_gloG1Unc =
                    gnss_measurement_info.gpsGloInterSystemBias.timeBiasUnc * 1000000;
            mTimeBiases.flags |= BIAS_GPSL1_GLOG1_UNC_VALID;
        }
    }

    if (1 == gnss_measurement_info.gpsBdsInterSystemBias_valid) {
        qmiLocInterSystemBiasStructT_v02* interSystemBias =
                (qmiLocInterSystemBiasStructT_v02*)&gnss_measurement_info.gpsBdsInterSystemBias;

        getInterSystemTimeBias("gpsBdsInterSystemBias",
                                svMeasSetHead.gpsBdsInterSystemBias, interSystemBias);
        svMeasSetHead.flags |= GNSS_SV_MEAS_HEADER_HAS_GPS_BDS_INTER_SYSTEM_BIAS;

        if (gnss_measurement_info.gpsBdsInterSystemBias.validMask &
            QMI_LOC_SYS_TIME_BIAS_VALID_V02) {
            mTimeBiases.gpsL1_bdsB1 =
                    -gnss_measurement_info.gpsBdsInterSystemBias.timeBias * 1000000;
            mTimeBiases.flags |= BIAS_GPSL1_BDSB1_VALID;
        }
        if (gnss_measurement_info.gpsBdsInterSystemBias.validMask &
            QMI_LOC_SYS_TIME_BIAS_UNC_VALID_V02) {
            mTimeBiases.gpsL1_bdsB1Unc =
                    gnss_measurement_info.gpsBdsInterSystemBias.timeBiasUnc * 1000000;
            mTimeBiases.flags |= BIAS_GPSL1_BDSB1_UNC_VALID;
        }
    }

    if (1 == gnss_measurement_info.gpsGalInterSystemBias_valid) {
        qmiLocInterSystemBiasStructT_v02* interSystemBias =
                (qmiLocInterSystemBiasStructT_v02*)&gnss_measurement_info.gpsGalInterSystemBias;

        getInterSystemTimeBias("gpsGalInterSystemBias",
                               svMeasSetHead.gpsGalInterSystemBias, interSystemBias);
        svMeasSetHead.flags |= GNSS_SV_MEAS_HEADER_HAS_GPS_GAL_INTER_SYSTEM_BIAS;

        if (gnss_measurement_info.gpsGalInterSystemBias.validMask &
            QMI_LOC_SYS_TIME_BIAS_VALID_V02) {
            mTimeBiases.gpsL1_galE1 =
                    -gnss_measurement_info.gpsGalInterSystemBias.timeBias * 1000000;
            mTimeBiases.flags |= BIAS_GPSL1_GALE1_VALID;
        }
        if (gnss_measurement_info.gpsGalInterSystemBias.validMask &
            QMI_LOC_SYS_TIME_BIAS_UNC_VALID_V02) {
            mTimeBiases.gpsL1_galE1Unc =
                    gnss_measurement_info.gpsGalInterSystemBias.timeBiasUnc * 1000000;
            mTimeBiases.flags |= BIAS_GPSL1_GALE1_UNC_VALID;
        }
    }

    if (1 == gnss_measurement_info.bdsGloInterSystemBias_valid) {
        qmiLocInterSystemBiasStructT_v02* interSystemBias =
                (qmiLocInterSystemBiasStructT_v02*)&gnss_measurement_info.bdsGloInterSystemBias;

        getInterSystemTimeBias("bdsGloInterSystemBias",
                               svMeasSetHead.bdsGloInterSystemBias, interSystemBias);
        svMeasSetHead.flags |= GNSS_SV_MEAS_HEADER_HAS_BDS_GLO_INTER_SYSTEM_BIAS;
    }

    if (1 == gnss_measurement_info.galGloInterSystemBias_valid) {
        qmiLocInterSystemBiasStructT_v02* interSystemBias =
                (qmiLocInterSystemBiasStructT_v02*)&gnss_measurement_info.galGloInterSystemBias;

        getInterSystemTimeBias("galGloInterSystemBias",
                                svMeasSetHead.galGloInterSystemBias, interSystemBias);
        svMeasSetHead.flags |= GNSS_SV_MEAS_HEADER_HAS_GAL_GLO_INTER_SYSTEM_BIAS;
    }

    if (1 == gnss_measurement_info.galBdsInterSystemBias_valid) {
        qmiLocInterSystemBiasStructT_v02* interSystemBias =
                (qmiLocInterSystemBiasStructT_v02*)&gnss_measurement_info.galBdsInterSystemBias;

        getInterSystemTimeBias("galBdsInterSystemBias",
                                svMeasSetHead.galBdsInterSystemBias, interSystemBias);
        svMeasSetHead.flags |= GNSS_SV_MEAS_HEADER_HAS_GAL_BDS_INTER_SYSTEM_BIAS;
    }

    if (1 == gnss_measurement_info.gpsNavicInterSystemBias_valid) {
        qmiLocInterSystemBiasStructT_v02* interSystemBias =
                (qmiLocInterSystemBiasStructT_v02*)&gnss_measurement_info.gpsNavicInterSystemBias;

        getInterSystemTimeBias("gpsNavicInterSystemBias",
                                svMeasSetHead.gpsNavicInterSystemBias, interSystemBias);
        svMeasSetHead.flags |= GNSS_SV_MEAS_HEADER_HAS_GPS_NAVIC_INTER_SYSTEM_BIAS;

        if (gnss_measurement_info.gpsNavicInterSystemBias.validMask &
            QMI_LOC_SYS_TIME_BIAS_VALID_V02) {
            mTimeBiases.gpsL1_navic =
                    -gnss_measurement_info.gpsNavicInterSystemBias.timeBias * 1000000;
            mTimeBiases.flags |= BIAS_GPSL1_NAVIC_VALID;
        }
        if (gnss_measurement_info.gpsNavicInterSystemBias.validMask &
            QMI_LOC_SYS_TIME_BIAS_UNC_VALID_V02) {
            mTimeBiases.gpsL1_navicUnc =
                    gnss_measurement_info.gpsNavicInterSystemBias.timeBiasUnc * 1000000;
            mTimeBiases.flags |= BIAS_GPSL1_NAVIC_UNC_VALID;
        }
    }

    if (1 == gnss_measurement_info.galNavicInterSystemBias_valid) {
        qmiLocInterSystemBiasStructT_v02* interSystemBias =
                (qmiLocInterSystemBiasStructT_v02*)&gnss_measurement_info.galNavicInterSystemBias;

        getInterSystemTimeBias("galNavicInterSystemBias",
                                svMeasSetHead.galNavicInterSystemBias, interSystemBias);
        svMeasSetHead.flags |= GNSS_SV_MEAS_HEADER_HAS_GAL_NAVIC_INTER_SYSTEM_BIAS;
    }

    if (1 == gnss_measurement_info.gloNavicInterSystemBias_valid) {
        qmiLocInterSystemBiasStructT_v02* interSystemBias =
                (qmiLocInterSystemBiasStructT_v02*)&gnss_measurement_info.gloNavicInterSystemBias;

        getInterSystemTimeBias("gloNavicInterSystemBias",
                                svMeasSetHead.gloNavicInterSystemBias, interSystemBias);
        svMeasSetHead.flags |= GNSS_SV_MEAS_HEADER_HAS_GLO_NAVIC_INTER_SYSTEM_BIAS;
    }

    if (1 == gnss_measurement_info.bdsNavicInterSystemBias_valid) {
        qmiLocInterSystemBiasStructT_v02* interSystemBias =
                (qmiLocInterSystemBiasStructT_v02*)&gnss_measurement_info.bdsNavicInterSystemBias;

        getInterSystemTimeBias("bdsNavicInterSystemBias",
                                svMeasSetHead.bdsNavicInterSystemBias, interSystemBias);
        svMeasSetHead.flags |= GNSS_SV_MEAS_HEADER_HAS_BDS_NAVIC_INTER_SYSTEM_BIAS;
    }

    if (1 == gnss_measurement_info.GpsL1L5TimeBias_valid) {
        qmiLocInterSystemBiasStructT_v02* interSystemBias =
                (qmiLocInterSystemBiasStructT_v02*)&gnss_measurement_info.GpsL1L5TimeBias;

        getInterSystemTimeBias("gpsL1L5TimeBias",
                                svMeasSetHead.gpsL1L5TimeBias, interSystemBias);
        svMeasSetHead.flags |= GNSS_SV_MEAS_HEADER_HAS_GPSL1L5_TIME_BIAS;

        if (gnss_measurement_info.GpsL1L5TimeBias.validMask & QMI_LOC_SYS_TIME_BIAS_VALID_V02) {
            mTimeBiases.gpsL1_gpsL5 = -gnss_measurement_info.GpsL1L5TimeBias.timeBias * 1000000;
            mTimeBiases.flags |= BIAS_GPSL1_GPSL5_VALID;
        }
        if (gnss_measurement_info.GpsL1L5TimeBias.validMask &
            QMI_LOC_SYS_TIME_BIAS_UNC_VALID_V02) {
            mTimeBiases.gpsL1_gpsL5Unc =
                    gnss_measurement_info.GpsL1L5TimeBias.timeBiasUnc * 1000000;
            mTimeBiases.flags |= BIAS_GPSL1_GPSL5_UNC_VALID;
        }
    }

    if (1 == gnss_measurement_info.GalE1E5aTimeBias_valid) {
        qmiLocInterSystemBiasStructT_v02* interSystemBias =
                (qmiLocInterSystemBiasStructT_v02*)&gnss_measurement_info.GalE1E5aTimeBias;

        getInterSystemTimeBias("galE1E5aTimeBias",
                                svMeasSetHead.galE1E5aTimeBias, interSystemBias);
        svMeasSetHead.flags |= GNSS_SV_MEAS_HEADER_HAS_GALE1E5A_TIME_BIAS;

        if (gnss_measurement_info.GalE1E5aTimeBias.validMask & QMI_LOC_SYS_TIME_BIAS_VALID_V02) {
            mTimeBiases.galE1_galE5a = -gnss_measurement_info.GalE1E5aTimeBias.timeBias * 1000000;
            mTimeBiases.flags |= BIAS_GALE1_GALE5A_VALID;
        }
        if (gnss_measurement_info.GalE1E5aTimeBias.validMask &
            QMI_LOC_SYS_TIME_BIAS_UNC_VALID_V02) {
            mTimeBiases.galE1_galE5aUnc =
                    gnss_measurement_info.GalE1E5aTimeBias.timeBiasUnc * 1000000;
            mTimeBiases.flags |= BIAS_GALE1_GALE5A_UNC_VALID;
        }
    }

    if (1 == gnss_measurement_info.BdsB1iB2aTimeBias_valid) {
        qmiLocInterSystemBiasStructT_v02* interSystemBias =
                (qmiLocInterSystemBiasStructT_v02*)&gnss_measurement_info.BdsB1iB2aTimeBias;

        getInterSystemTimeBias("bdsB1iB2aTimeBias",
                               svMeasSetHead.bdsB1iB2aTimeBias, interSystemBias);
        svMeasSetHead.flags |= GNSS_SV_MEAS_HEADER_HAS_BDSB1IB2A_TIME_BIAS;

        if (gnss_measurement_info.BdsB1iB2aTimeBias.validMask & QMI_LOC_SYS_TIME_BIAS_VALID_V02) {
            mTimeBiases.bdsB1_bdsB2a = -gnss_measurement_info.BdsB1iB2aTimeBias.timeBias * 1000000;
            mTimeBiases.flags |= BIAS_BDSB1_BDSB2A_VALID;
        }
        if (gnss_measurement_info.BdsB1iB2aTimeBias.validMask &
            QMI_LOC_SYS_TIME_BIAS_UNC_VALID_V02) {
            mTimeBiases.bdsB1_bdsB2aUnc =
                    gnss_measurement_info.BdsB1iB2aTimeBias.timeBiasUnc * 1000000;
            mTimeBiases.flags |= BIAS_BDSB1_BDSB2A_UNC_VALID;
        }
    }

    if (1 == gnss_measurement_info.BdsB1iB1cTimeBias_valid) {
        if (gnss_measurement_info.BdsB1iB1cTimeBias.validMask & QMI_LOC_SYS_TIME_BIAS_VALID_V02) {
            mTimeBiases.bdsB1_bdsB1c = -gnss_measurement_info.BdsB1iB1cTimeBias.timeBias * 1000000;
            mTimeBiases.flags |= BIAS_BDSB1_BDSB1C_VALID;
        }
        if (gnss_measurement_info.BdsB1iB1cTimeBias.validMask &
            QMI_LOC_SYS_TIME_BIAS_UNC_VALID_V02) {
            mTimeBiases.bdsB1_bdsB1cUnc =
                    gnss_measurement_info.BdsB1iB1cTimeBias.timeBiasUnc * 1000000;
            mTimeBiases.flags |= BIAS_BDSB1_BDSB1C_UNC_VALID;
        }
    }

    if (1 == gnss_measurement_info.GpsL1L2cTimeBias_valid) {
        qmiLocInterSystemBiasStructT_v02* interSystemBias =
                (qmiLocInterSystemBiasStructT_v02*)&gnss_measurement_info.GpsL1L2cTimeBias;

        getInterSystemTimeBias("gpsL1L2cTimeBias",
                               svMeasSetHead.gpsL1L2cTimeBias, interSystemBias);
        svMeasSetHead.flags |= GNSS_SV_MEAS_HEADER_HAS_GPSL1L2C_TIME_BIAS;
    }

    if (1 == gnss_measurement_info.GloG1G2TimeBias_valid) {
        qmiLocInterSystemBiasStructT_v02* interSystemBias =
                (qmiLocInterSystemBiasStructT_v02*)&gnss_measurement_info.GloG1G2TimeBias;

        getInterSystemTimeBias("gloG1G2TimeBias",
                               svMeasSetHead.gloG1G2TimeBias, interSystemBias);
        svMeasSetHead.flags |= GNSS_SV_MEAS_HEADER_HAS_GLOG1G2_TIME_BIAS;
    }

    if (1 == gnss_measurement_info.BdsB1iB1cTimeBias_valid) {
        qmiLocInterSystemBiasStructT_v02* interSystemBias =
                (qmiLocInterSystemBiasStructT_v02*)&gnss_measurement_info.BdsB1iB1cTimeBias;

        getInterSystemTimeBias("bdsB1iB1cTimeBias",
                               svMeasSetHead.bdsB1iB1cTimeBias, interSystemBias);
        svMeasSetHead.flags |= GNSS_SV_MEAS_HEADER_HAS_BDSB1IB1C_TIME_BIAS;
    }

    if (1 == gnss_measurement_info.GalE1E5bTimeBias_valid) {
        qmiLocInterSystemBiasStructT_v02* interSystemBias =
                (qmiLocInterSystemBiasStructT_v02*)&gnss_measurement_info.GalE1E5bTimeBias;

        getInterSystemTimeBias("galE1E5bTimeBias",
                               svMeasSetHead.galE1E5bTimeBias, interSystemBias);
        svMeasSetHead.flags |= GNSS_SV_MEAS_HEADER_HAS_GALE1E5B_TIME_BIAS;
    }

    if (1 == gnss_measurement_info.gloTime_valid) {
        GnssGloTimeStructType & gloSystemTime = svMeasSetHead.gloSystemTime;

        gloSystemTime.gloFourYear = gnss_measurement_info.gloTime.gloFourYear;
        gloSystemTime.gloDays = gnss_measurement_info.gloTime.gloDays;
        gloSystemTime.gloMsec = gnss_measurement_info.gloTime.gloMsec;
        gloSystemTime.gloClkTimeBias = gnss_measurement_info.gloTime.gloClkTimeBias;
        gloSystemTime.gloClkTimeUncMs = gnss_measurement_info.gloTime.gloClkTimeUncMs;
        gloSystemTime.validityMask |= (GNSS_GLO_FOUR_YEAR_VALID |
            GNSS_CLO_DAYS_VALID |
            GNSS_GLO_MSEC_VALID |
            GNSS_GLO_CLK_TIME_BIAS_VALID |
            GNSS_GLO_CLK_TIME_BIAS_UNC_VALID);

        if (gnss_measurement_info.systemTimeExt_valid) {
            gloSystemTime.refFCount = gnss_measurement_info.systemTimeExt.refFCount;
            gloSystemTime.validityMask |= GNSS_GLO_REF_FCOUNT_VALID;
        }

        if (gnss_measurement_info.numClockResets_valid) {
            gloSystemTime.numClockResets = gnss_measurement_info.numClockResets;
            gloSystemTime.validityMask |= GNSS_GLO_NUM_CLOCK_RESETS_VALID;
        }

        svMeasSetHead.flags |= GNSS_SV_MEAS_HEADER_HAS_GLO_SYSTEM_TIME;
    }

    if ((1 == gnss_measurement_info.systemTime_valid) ||
        (1 == gnss_measurement_info.systemTimeExt_valid)) {

        GnssSystemTimeStructType* systemTimePtr = nullptr;
        Gnss_LocGnssTimeExtStructType* systemTimeExtPtr = nullptr;
        GpsSvMeasHeaderFlags systemTimeFlags = 0x0;
        GpsSvMeasHeaderFlags systemTimeExtFlags = 0x0;

        switch (locSvSystemType) {
        case GNSS_LOC_SV_SYSTEM_GPS:
            systemTimePtr = &svMeasSetHead.gpsSystemTime;
            systemTimeExtPtr = &svMeasSetHead.gpsSystemTimeExt;
            systemTimeFlags = GNSS_SV_MEAS_HEADER_HAS_GPS_SYSTEM_TIME;
            systemTimeExtFlags = GNSS_SV_MEAS_HEADER_HAS_GPS_SYSTEM_TIME_EXT;
            if (gnss_measurement_info.systemTime_valid) {
                mTimeBiases.gpsL1 = gnss_measurement_info.systemTime.systemClkTimeBias * 1000000;
                mTimeBiases.gpsL1Unc =
                        gnss_measurement_info.systemTime.systemClkTimeUncMs * 1000000;
                mTimeBiases.flags |= BIAS_GPSL1_VALID;
                mTimeBiases.flags |= BIAS_GPSL1_UNC_VALID;
            }
            break;
        case GNSS_LOC_SV_SYSTEM_GALILEO:
            systemTimePtr = &svMeasSetHead.galSystemTime;
            systemTimeExtPtr = &svMeasSetHead.galSystemTimeExt;
            systemTimeFlags = GNSS_SV_MEAS_HEADER_HAS_GAL_SYSTEM_TIME;
            systemTimeExtFlags = GNSS_SV_MEAS_HEADER_HAS_GAL_SYSTEM_TIME_EXT;
            if (gnss_measurement_info.systemTime_valid) {
                mTimeBiases.galE1 = gnss_measurement_info.systemTime.systemClkTimeBias * 1000000;
                mTimeBiases.galE1Unc =
                    gnss_measurement_info.systemTime.systemClkTimeUncMs * 1000000;
                mTimeBiases.flags |= BIAS_GALE1_VALID;
                mTimeBiases.flags |= BIAS_GALE1_UNC_VALID;
            }
            break;
        case GNSS_LOC_SV_SYSTEM_BDS:
            systemTimePtr = &svMeasSetHead.bdsSystemTime;
            systemTimeExtPtr = &svMeasSetHead.bdsSystemTimeExt;
            systemTimeFlags = GNSS_SV_MEAS_HEADER_HAS_BDS_SYSTEM_TIME;
            systemTimeExtFlags = GNSS_SV_MEAS_HEADER_HAS_BDS_SYSTEM_TIME_EXT;
            if (gnss_measurement_info.systemTime_valid) {
                mTimeBiases.bdsB1 = gnss_measurement_info.systemTime.systemClkTimeBias * 1000000;
                mTimeBiases.bdsB1Unc =
                    gnss_measurement_info.systemTime.systemClkTimeUncMs * 1000000;
                mTimeBiases.flags |= BIAS_BDSB1_VALID;
                mTimeBiases.flags |= BIAS_BDSB1_UNC_VALID;
            }
            break;
        case GNSS_LOC_SV_SYSTEM_QZSS:
            systemTimePtr = &svMeasSetHead.qzssSystemTime;
            systemTimeExtPtr = &svMeasSetHead.qzssSystemTimeExt;
            systemTimeFlags = GNSS_SV_MEAS_HEADER_HAS_QZSS_SYSTEM_TIME;
            systemTimeExtFlags = GNSS_SV_MEAS_HEADER_HAS_QZSS_SYSTEM_TIME_EXT;
            break;
        case GNSS_LOC_SV_SYSTEM_GLONASS:
            systemTimeExtPtr = &svMeasSetHead.gloSystemTimeExt;
            systemTimeExtFlags = GNSS_SV_MEAS_HEADER_HAS_GLO_SYSTEM_TIME_EXT;
            break;
        case GNSS_LOC_SV_SYSTEM_NAVIC:
            systemTimePtr = &svMeasSetHead.navicSystemTime;
            systemTimeExtPtr = &svMeasSetHead.navicSystemTimeExt;
            systemTimeFlags = GNSS_SV_MEAS_HEADER_HAS_NAVIC_SYSTEM_TIME;
            systemTimeExtFlags = GNSS_SV_MEAS_HEADER_HAS_NAVIC_SYSTEM_TIME_EXT;
            break;
        default:
            break;
        }

        if (systemTimePtr) {
            if (gnss_measurement_info.systemTime_valid) {
                systemTimePtr->systemWeek =
                    gnss_measurement_info.systemTime.systemWeek;
                systemTimePtr->systemMsec =
                    gnss_measurement_info.systemTime.systemMsec;
                systemTimePtr->systemClkTimeBias =
                    gnss_measurement_info.systemTime.systemClkTimeBias;
                systemTimePtr->systemClkTimeUncMs =
                    gnss_measurement_info.systemTime.systemClkTimeUncMs;
                systemTimePtr->validityMask |= (GNSS_SYSTEM_TIME_WEEK_VALID |
                    GNSS_SYSTEM_TIME_WEEK_MS_VALID |
                    GNSS_SYSTEM_CLK_TIME_BIAS_VALID |
                    GNSS_SYSTEM_CLK_TIME_BIAS_UNC_VALID);
                svMeasSetHead.flags |= systemTimeFlags;
            }

            if (gnss_measurement_info.systemTimeExt_valid) {
                systemTimePtr->refFCount = gnss_measurement_info.systemTimeExt.refFCount;
                systemTimePtr->validityMask |= GNSS_SYSTEM_REF_FCOUNT_VALID;
                svMeasSetHead.flags |= systemTimeFlags;
            }

            if (gnss_measurement_info.numClockResets_valid) {
                systemTimePtr->numClockResets = gnss_measurement_info.numClockResets;
                systemTimePtr->validityMask |= GNSS_SYSTEM_NUM_CLOCK_RESETS_VALID;
                svMeasSetHead.flags |= systemTimeFlags;
            }
        }

        if (systemTimeExtPtr) {
            if (gnss_measurement_info.systemTimeExt_valid) {
                systemTimeExtPtr->size = sizeof(Gnss_LocGnssTimeExtStructType);

                systemTimeExtPtr->systemRtc_valid =
                    gnss_measurement_info.systemTimeExt.systemRtc_valid;
                systemTimeExtPtr->systemRtcMs =
                    gnss_measurement_info.systemTimeExt.systemRtcMs;

                svMeasSetHead.flags |= systemTimeExtFlags;
            }
        }
    }

    if (gnss_measurement_info.dgnssCorrectionSourceT_valid) {
        svMeasSetHead.dgnssCorrectionSourceType =
                (LocDgnssCorrectionSourceType)gnss_measurement_info.dgnssCorrectionSourceT;
        svMeasSetHead.flags |= GNSS_SV_MEAS_HEADER_HAS_DGNSS_CORRECTION_SOURCE_TYPE;
    }
    if (gnss_measurement_info.dgnssCorrectionSourceID_valid) {
        svMeasSetHead.dgnssCorrectionSourceID =
                gnss_measurement_info.dgnssCorrectionSourceID;
        svMeasSetHead.flags |= GNSS_SV_MEAS_HEADER_HAS_DGNSS_CORRECTION_SOURCE_ID;

    }
    if (gnss_measurement_info.dgnssRefStationId_valid) {
        svMeasSetHead.dgnssRefStationId =
                gnss_measurement_info.dgnssRefStationId;
        svMeasSetHead.flags |= GNSS_SV_MEAS_HEADER_HAS_DGNSS_REF_STATION_ID;
    }
}

/* convert and report ODCPI request */
void LocApiV02::requestOdcpi(const qmiLocEventWifiReqIndMsgT_v02& qmiReq)
{
    LOC_LOGv("ODCPI Request: requestType %d", qmiReq.requestType);

    OdcpiRequestInfo req = {};
    req.size = sizeof(OdcpiRequestInfo);

    if (eQMI_LOC_WIFI_START_PERIODIC_HI_FREQ_FIXES_V02 == qmiReq.requestType ||
            eQMI_LOC_WIFI_START_PERIODIC_KEEP_WARM_V02 == qmiReq.requestType) {
        req.type = ODCPI_REQUEST_TYPE_START;
    } else if (eQMI_LOC_WIFI_STOP_PERIODIC_FIXES_V02 == qmiReq.requestType){
        req.type = ODCPI_REQUEST_TYPE_STOP;
    } else {
        LOC_LOGe("Invalid request type");
        return;
    }

    if (qmiReq.e911Mode_valid) {
        req.isEmergencyMode = qmiReq.e911Mode == 1 ? true : false;
    }

    if (qmiReq.tbfInMs_valid) {
        req.tbfMillis = qmiReq.tbfInMs;
    }

    LocApiBase::requestOdcpi(req);
}

void LocApiV02::wifiStatusInformSync()
{
    qmiLocNotifyWifiStatusReqMsgT_v02 wifiStatusReq;
    memset(&wifiStatusReq, 0, sizeof(wifiStatusReq));
    wifiStatusReq.wifiStatus = eQMI_LOC_WIFI_STATUS_AVAILABLE_V02;

    LOC_LOGv("Informing wifi status available.");
    LOC_SEND_SYNC_REQ(NotifyWifiStatus, NOTIFY_WIFI_STATUS, wifiStatusReq);
}

#define FIRST_BDS_D2_SV_PRN 1
#define LAST_BDS_D2_SV_PRN  5
#define IS_BDS_GEO_SV(svId, gnssType) ( ((gnssType == GNSS_SV_TYPE_BEIDOU) && \
                                        (svId <= LAST_BDS_D2_SV_PRN) && \
                                        (svId >= FIRST_BDS_D2_SV_PRN)) ? true : false )

/*convert GnssMeasurement type from QMI LOC to loc eng format*/
bool LocApiV02 :: convertGnssMeasurements(
    const qmiLocEventGnssSvMeasInfoIndMsgT_v02& gnss_measurement_report_ptr,
    int index, bool isExt, bool validDgnssSvMeas)
{
    bool bAgcIsPresent = false;
    qmiLocSVMeasurementStructT_v02 gnss_measurement_info;
    uint32_t count = mGnssMeasurements->gnssMeasNotification.count;

    LOC_LOGv("entering extMeas %d, qmi sv index %d, current sv count %d", isExt, index, count);
    if (isExt) {
        gnss_measurement_info = gnss_measurement_report_ptr.extSvMeasurement[index];
    } else {
        gnss_measurement_info = gnss_measurement_report_ptr.svMeasurement[index];
    }

    GnssMeasurementsData& measurementData =
        mGnssMeasurements->gnssMeasNotification.measurements[count];

    Gnss_SVMeasurementStructType& svMeas =
        mGnssMeasurements->gnssSvMeasurementSet.svMeas[count];

    svMeas.size = sizeof(Gnss_SVMeasurementStructType);
    svMeas.gnssSystem = getLocApiSvSystemType(gnss_measurement_report_ptr.system);
    svMeas.gnssSvId = gnss_measurement_info.gnssSvId;
    svMeas.gloFrequency = gnss_measurement_info.gloFrequency;
    if (gnss_measurement_report_ptr.gnssSignalType_valid) {
        svMeas.gnssSignalTypeMask =
                convertQmiGnssSignalType(gnss_measurement_report_ptr.gnssSignalType);
    } else {
        svMeas.gnssSignalTypeMask =
                getDefaultGnssSignalTypeMask(gnss_measurement_report_ptr.system);
    }
    if (gnss_measurement_info.validMask & QMI_LOC_SV_LOSSOFLOCK_VALID_V02) {
        svMeas.lossOfLock = (bool)gnss_measurement_info.lossOfLock;
    }

    svMeas.svStatus = (Gnss_LocSvSearchStatusEnumT)gnss_measurement_info.svStatus;

    if (gnss_measurement_info.validMask & QMI_LOC_SV_HEALTH_VALID_V02) {
        svMeas.healthStatus_valid = 1;
        svMeas.healthStatus = (uint8_t)gnss_measurement_info.healthStatus;
    }

    svMeas.svInfoMask = (Gnss_LocSvInfoMaskT)gnss_measurement_info.svInfoMask;
    svMeas.CNo = gnss_measurement_info.CNo;
    svMeas.gloRfLoss = gnss_measurement_info.gloRfLoss;
    svMeas.measLatency = gnss_measurement_info.measLatency;

    // SVTimeSpeed
    svMeas.svTimeSpeed.size = sizeof(Gnss_LocSVTimeSpeedStructType);
    svMeas.svTimeSpeed.svMs = gnss_measurement_info.svTimeSpeed.svTimeMs;
    svMeas.svTimeSpeed.svSubMs = gnss_measurement_info.svTimeSpeed.svTimeSubMs;
    svMeas.svTimeSpeed.svTimeUncMs = gnss_measurement_info.svTimeSpeed.svTimeUncMs;
    svMeas.svTimeSpeed.dopplerShift = gnss_measurement_info.svTimeSpeed.dopplerShift;
    svMeas.svTimeSpeed.dopplerShiftUnc = gnss_measurement_info.svTimeSpeed.dopplerShiftUnc;

    svMeas.validMeasStatusMask = gnss_measurement_info.validMeasStatusMask;
    qmiLocSvMeasStatusMaskT_v02 measStatus = gnss_measurement_info.measurementStatus;
    svMeas.measurementStatus = GNSS_LOC_MEAS_STATUS_NULL;
    // Convert qmiSvMeas.measurementStatus to svMeas.measurementStatus
    if (QMI_LOC_MASK_MEAS_STATUS_SM_VALID_V02 & measStatus) {
        svMeas.measurementStatus |= GNSS_LOC_MEAS_STATUS_SM_VALID;
    }
    if (QMI_LOC_MASK_MEAS_STATUS_SB_VALID_V02 & measStatus) {
        svMeas.measurementStatus |= GNSS_LOC_MEAS_STATUS_SB_VALID;
    }
    if (QMI_LOC_MASK_MEAS_STATUS_MS_VALID_V02 & measStatus) {
        svMeas.measurementStatus |= GNSS_LOC_MEAS_STATUS_MS_VALID;
    }
    if (QMI_LOC_MASK_MEAS_STATUS_BE_CONFIRM_V02 & measStatus) {
        svMeas.measurementStatus |= GNSS_LOC_MEAS_STATUS_BE_CONFIRM;
    }
    if (QMI_LOC_MASK_MEAS_STATUS_VELOCITY_VALID_V02 & measStatus) {
        svMeas.measurementStatus |= GNSS_LOC_MEAS_STATUS_VELOCITY_VALID;
    }
    if (QMI_LOC_MASK_MEAS_STATUS_VELOCITY_FINE_V02 & measStatus) {
        svMeas.measurementStatus |= GNSS_LOC_MEAS_STATUS_VELOCITY_FINE;
    }
    if (QMI_LOC_MASK_MEAS_STATUS_LP_VALID_V02 & measStatus) {
        svMeas.measurementStatus |= GNSS_LOC_MEAS_STATUS_LP_VALID;
    }
    if (QMI_LOC_MASK_MEAS_STATUS_LP_POS_VALID_V02 & measStatus) {
        svMeas.measurementStatus |= GNSS_LOC_MEAS_STATUS_LP_POS_VALID;
    }
    if (QMI_LOC_MASK_MEAS_STATUS_FROM_RNG_DIFF_V02 & measStatus) {
        svMeas.measurementStatus |= GNSS_LOC_MEAS_STATUS_FROM_RNG_DIFF;
    }
    if (QMI_LOC_MASK_MEAS_STATUS_FROM_VE_DIFF_V02 & measStatus) {
        svMeas.measurementStatus |= GNSS_LOC_MEAS_STATUS_FROM_VE_DIFF;
    }
    if (QMI_LOC_MASK_MEAS_STATUS_GNSS_FRESH_MEAS_VALID_V02 & measStatus) {
        svMeas.measurementStatus |= GNSS_LOC_MEAS_STATUS_GNSS_FRESH_MEAS;
    }
    if (gnss_measurement_info.validMask & QMI_LOC_SV_MULTIPATH_EST_VALID_V02) {
        svMeas.multipathEstValid = 1;
        svMeas.multipathEstimate = gnss_measurement_info.multipathEstimate;
    }

    if (gnss_measurement_info.validMask & QMI_LOC_SV_FINE_SPEED_VALID_V02) {
        svMeas.fineSpeedValid = 1;
        svMeas.fineSpeed = gnss_measurement_info.fineSpeed;
    }
    if (gnss_measurement_info.validMask & QMI_LOC_SV_FINE_SPEED_UNC_VALID_V02) {
        svMeas.fineSpeedUncValid = 1;
        svMeas.fineSpeedUnc = gnss_measurement_info.fineSpeedUnc;
    }
    if (gnss_measurement_info.validMask & QMI_LOC_SV_CARRIER_PHASE_VALID_V02) {
        svMeas.carrierPhaseValid = 1;
        svMeas.carrierPhase = gnss_measurement_info.carrierPhase;
    }
    if (gnss_measurement_info.validMask & QMI_LOC_SV_SV_DIRECTION_VALID_V02) {
        svMeas.svDirectionValid = 1;
        svMeas.svElevation = gnss_measurement_info.svElevation;
        svMeas.svAzimuth = gnss_measurement_info.svAzimuth;
    }
    if (gnss_measurement_info.validMask & QMI_LOC_SV_CYCLESLIP_COUNT_VALID_V02) {
        svMeas.cycleSlipCountValid = 1;
        svMeas.cycleSlipCount = gnss_measurement_info.cycleSlipCount;
    }

    if (validDgnssSvMeas) {
        int dgnssSvMeasIndex = index;
        // adjust the dgnss meas index if we are processing external SV measurement
        if (isExt) {
            dgnssSvMeasIndex += gnss_measurement_report_ptr.svMeasurement_len;
        }
        const qmiLocDgnssSVMeasurementStructT_v02* dgnss_sv_meas_ptr =
                &gnss_measurement_report_ptr.dgnssSvMeasurement[dgnssSvMeasIndex];
        svMeas.dgnssSvMeas.dgnssMeasStatus = (LocSvDgnssMeasStatusMask)
                dgnss_sv_meas_ptr->dgnssMeasStatus,
        svMeas.dgnssSvMeas.diffDataEpochTimeMsec =
                dgnss_sv_meas_ptr->diffDataEpochTimeMsec;
        svMeas.dgnssSvMeas.prCorrMeters =
                dgnss_sv_meas_ptr->prCorrMeters;
        svMeas.dgnssSvMeas.prrCorrMetersPerSec =
                dgnss_sv_meas_ptr->prrCorrMetersPerSec;
    }

    if (!isExt) {
        uint32_t svMeas_len = gnss_measurement_report_ptr.svMeasurement_len;
        uint32_t svCarPhUnc_len = gnss_measurement_report_ptr.svCarrierPhaseUncertainty_len;
        if ((1 == gnss_measurement_report_ptr.svCarrierPhaseUncertainty_valid) &&
            (svMeas_len == svCarPhUnc_len)) {
            svMeas.carrierPhaseUncValid = 1;
            svMeas.carrierPhaseUnc =
                    gnss_measurement_report_ptr.svCarrierPhaseUncertainty[index];
        }
    } else {
        uint32_t extSvMeas_len = gnss_measurement_report_ptr.extSvMeasurement_len;
        uint32_t extSvCarPhUnc_len = gnss_measurement_report_ptr.extSvCarrierPhaseUncertainty_len;
        if ((1 == gnss_measurement_report_ptr.extSvCarrierPhaseUncertainty_valid) &&
            (extSvMeas_len == extSvCarPhUnc_len)) {
            svMeas.carrierPhaseUncValid = 1;
            svMeas.carrierPhaseUnc =
                    gnss_measurement_report_ptr.extSvCarrierPhaseUncertainty[index];
        }
    }

    // size
    measurementData.size = sizeof(GnssMeasurementsData);

    // flag initiation
    measurementData.flags = 0;

    // svid
    measurementData.svId = gnss_measurement_info.gnssSvId;

    // constellation
    switch (gnss_measurement_report_ptr.system)
    {
        case eQMI_LOC_SV_SYSTEM_GPS_V02:
            measurementData.svType = GNSS_SV_TYPE_GPS;
            break;

        case eQMI_LOC_SV_SYSTEM_GALILEO_V02:
            measurementData.svType = GNSS_SV_TYPE_GALILEO;
            break;

        case eQMI_LOC_SV_SYSTEM_SBAS_V02:
            measurementData.svType = GNSS_SV_TYPE_SBAS;
            break;

        case eQMI_LOC_SV_SYSTEM_GLONASS_V02:
            measurementData.svType = GNSS_SV_TYPE_GLONASS;
            measurementData.gloFrequency = gnss_measurement_info.gloFrequency;
            break;

        case eQMI_LOC_SV_SYSTEM_BDS_V02:
            measurementData.svType = GNSS_SV_TYPE_BEIDOU;
            break;

        case eQMI_LOC_SV_SYSTEM_QZSS_V02:
            measurementData.svType = GNSS_SV_TYPE_QZSS;
            break;

        case eQMI_LOC_SV_SYSTEM_NAVIC_V02:
            measurementData.svType = GNSS_SV_TYPE_NAVIC;
            break;

        default:
            measurementData.svType = GNSS_SV_TYPE_UNKNOWN;
            break;
    }

    // time_offset_ns
    if (0 != gnss_measurement_info.measLatency)
    {
        LOC_LOGV("%s:%d]: measLatency is not 0\n", __func__, __LINE__);
    }
    measurementData.timeOffsetNs = 0.0;

    // stateMask & receivedSvTimeNs & received_gps_tow_uncertainty_ns
    uint64_t validMeasStatus = gnss_measurement_info.measurementStatus &
                               gnss_measurement_info.validMeasStatusMask;
    uint64_t bitSynMask = QMI_LOC_MASK_MEAS_STATUS_BE_CONFIRM_V02 |
                          QMI_LOC_MASK_MEAS_STATUS_SB_VALID_V02;
    double gpsTowUncNs = (double)gnss_measurement_info.svTimeSpeed.svTimeUncMs * 1e6;

    bool bBandNotAvailable = !gnss_measurement_report_ptr.gnssSignalType_valid;
    qmiLocGnssSignalTypeMaskT_v02 gnssBand;

    if (gnss_measurement_report_ptr.gnssSignalType_valid) {
        gnssBand = gnss_measurement_report_ptr.gnssSignalType;
    }

    measurementData.stateMask = GNSS_MEASUREMENTS_STATE_UNKNOWN_BIT;
    measurementData.receivedSvTimeNs = 0;
    measurementData.receivedSvTimeUncertaintyNs = 0;

    // Deal with Galileo first since it is special
    uint64_t galSVstateMask = 0;
    if (GNSS_SV_TYPE_GALILEO == measurementData.svType &&
        (bBandNotAvailable ||
        (QMI_LOC_MASK_GNSS_SIGNAL_TYPE_GALILEO_E1_C_V02 == gnssBand))) {

        galSVstateMask = GNSS_MEASUREMENTS_STATE_GAL_E1BC_CODE_LOCK_BIT;

        if (gnss_measurement_info.measurementStatus &
            QMI_LOC_MASK_MEAS_STATUS_100MS_STAT_BIT_VALID_V02) {
            galSVstateMask |= GNSS_MEASUREMENTS_STATE_GAL_E1C_2ND_CODE_LOCK_BIT;
        }

        if (gnss_measurement_info.measurementStatus &
            QMI_LOC_MASK_MEAS_STATUS_2S_STAT_BIT_VALID_V02) {
            galSVstateMask |= GNSS_MEASUREMENTS_STATE_GAL_E1B_PAGE_SYNC_BIT;
        }
    }
    // now deal with all constellations
    bool bIsL5orE5 = false;
    // L5
    if (GNSS_SV_TYPE_GPS == measurementData.svType &&
        (bBandNotAvailable ||
        (QMI_LOC_MASK_GNSS_SIGNAL_TYPE_GPS_L5_Q_V02 == gnssBand))) {
        bIsL5orE5 = true;
    }
    // E5
    if (GNSS_SV_TYPE_GALILEO == measurementData.svType &&
        (bBandNotAvailable ||
        (QMI_LOC_MASK_GNSS_SIGNAL_TYPE_GALILEO_E5A_Q_V02 == gnssBand))) {
        bIsL5orE5 = true;
    }

    if (validMeasStatus & QMI_LOC_MASK_MEAS_STATUS_MS_VALID_V02) {
        /* sub-frame decode & TOW decode */
        measurementData.stateMask |= (GNSS_MEASUREMENTS_STATE_SUBFRAME_SYNC_BIT |
                                      GNSS_MEASUREMENTS_STATE_TOW_DECODED_BIT |
                                      GNSS_MEASUREMENTS_STATE_TOW_KNOWN_BIT |
                                      GNSS_MEASUREMENTS_STATE_BIT_SYNC_BIT |
                                      GNSS_MEASUREMENTS_STATE_CODE_LOCK_BIT);
        // GLO
        if (GNSS_SV_TYPE_GLONASS == measurementData.svType &&
            (bBandNotAvailable ||
            (QMI_LOC_MASK_GNSS_SIGNAL_TYPE_GLONASS_G1_V02 == gnssBand))) {

            measurementData.stateMask |= (GNSS_MEASUREMENTS_STATE_GLO_TOD_KNOWN_BIT |
                                          GNSS_MEASUREMENTS_STATE_GLO_TOD_DECODED_BIT |
                                          GNSS_MEASUREMENTS_STATE_GLO_STRING_SYNC_BIT);
        }

        // GAL
        measurementData.stateMask |= galSVstateMask;

        // BDS
        if (IS_BDS_GEO_SV(measurementData.svId, measurementData.svType)) {
            /* BDS_GEO SV transmitting D2 signal */
            measurementData.stateMask |= (GNSS_MEASUREMENTS_STATE_BDS_D2_BIT_SYNC_BIT |
                                          GNSS_MEASUREMENTS_STATE_BDS_D2_SUBFRAME_SYNC_BIT);
        }

        // L5 or E5
        if (bIsL5orE5) {
            measurementData.stateMask |= GNSS_MEASUREMENTS_STATE_2ND_CODE_LOCK_BIT;
        }

        measurementData.receivedSvTimeNs =
            ((int64_t)gnss_measurement_info.svTimeSpeed.svTimeMs * 1000000) +
            (int64_t)(gnss_measurement_info.svTimeSpeed.svTimeSubMs * 1e6);

        measurementData.receivedSvTimeUncertaintyNs = (int64_t)gpsTowUncNs;

    } else if ((validMeasStatus & bitSynMask) == bitSynMask) {
        /* bit sync */
        measurementData.stateMask |= (GNSS_MEASUREMENTS_STATE_BIT_SYNC_BIT |
                                      GNSS_MEASUREMENTS_STATE_SYMBOL_SYNC_BIT |
                                      GNSS_MEASUREMENTS_STATE_CODE_LOCK_BIT);
        measurementData.stateMask |= galSVstateMask;

        // L5 or E5
        if (bIsL5orE5) {
            measurementData.stateMask |= GNSS_MEASUREMENTS_STATE_2ND_CODE_LOCK_BIT;
        }

        measurementData.receivedSvTimeNs =
            (((int64_t)gnss_measurement_info.svTimeSpeed.svTimeMs * 1000000) +
            (int64_t)(gnss_measurement_info.svTimeSpeed.svTimeSubMs * 1e6)) % (int64_t)20;

        measurementData.receivedSvTimeUncertaintyNs = (int64_t)gpsTowUncNs;

    } else if (validMeasStatus & QMI_LOC_MASK_MEAS_STATUS_SM_VALID_V02) {
        /* code lock */
        measurementData.stateMask |= GNSS_MEASUREMENTS_STATE_CODE_LOCK_BIT;
        measurementData.stateMask |= galSVstateMask;

        measurementData.receivedSvTimeNs =
            (int64_t)(gnss_measurement_info.svTimeSpeed.svTimeSubMs * 1e6);

        measurementData.receivedSvTimeUncertaintyNs = (int64_t)gpsTowUncNs;
    }

    // carrierToNoiseDbHz
    measurementData.carrierToNoiseDbHz = gnss_measurement_info.CNo/10.0;

    if (QMI_LOC_MASK_MEAS_STATUS_VELOCITY_FINE_V02 == (gnss_measurement_info.measurementStatus & QMI_LOC_MASK_MEAS_STATUS_VELOCITY_FINE_V02))
    {
        LOC_LOGV ("%s:%d]: FINE mS=0x%4" PRIX64 " fS=%f fSU=%f dS=%f dSU=%f\n", __func__, __LINE__,
        gnss_measurement_info.measurementStatus,
        gnss_measurement_info.fineSpeed, gnss_measurement_info.fineSpeedUnc,
        gnss_measurement_info.svTimeSpeed.dopplerShift, gnss_measurement_info.svTimeSpeed.dopplerShiftUnc);
        // pseudorangeRateMps
        measurementData.pseudorangeRateMps = gnss_measurement_info.fineSpeed;

        // pseudorangeRateUncertaintyMps
        measurementData.pseudorangeRateUncertaintyMps = gnss_measurement_info.fineSpeedUnc;
    }
    else
    {
        LOC_LOGV ("%s:%d]: COARSE mS=0x%4" PRIX64 " fS=%f fSU=%f dS=%f dSU=%f\n", __func__, __LINE__,
        gnss_measurement_info.measurementStatus,
        gnss_measurement_info.fineSpeed, gnss_measurement_info.fineSpeedUnc,
        gnss_measurement_info.svTimeSpeed.dopplerShift, gnss_measurement_info.svTimeSpeed.dopplerShiftUnc);
        // pseudorangeRateMps
        measurementData.pseudorangeRateMps = gnss_measurement_info.svTimeSpeed.dopplerShift;

        // pseudorangeRateUncertaintyMps
        measurementData.pseudorangeRateUncertaintyMps = gnss_measurement_info.svTimeSpeed.dopplerShiftUnc;
    }

    // carrier frequency
    if (gnss_measurement_report_ptr.gnssSignalType_valid) {
        LOC_LOGv("gloFrequency = 0x%X, sigType=%" PRIu64,
                 gnss_measurement_info.gloFrequency, gnss_measurement_report_ptr.gnssSignalType);
        measurementData.carrierFrequencyHz = convertSignalTypeToCarrierFrequency(
                gnss_measurement_report_ptr.gnssSignalType, gnss_measurement_info.gloFrequency);
        measurementData.flags |= GNSS_MEASUREMENTS_DATA_CARRIER_FREQUENCY_BIT;
    }
    else {
        measurementData.carrierFrequencyHz = 0;
        // GLONASS is FDMA system, so each channel has its own carrier frequency
        // The formula is f(k) = fc + k * 0.5625;
        // This is applicable for GLONASS G1 only, where fc = 1602MHz
        if ((gnss_measurement_info.gloFrequency >= 1 && gnss_measurement_info.gloFrequency <= 14)) {
            measurementData.carrierFrequencyHz += (gnss_measurement_info.gloFrequency - 8) * 562500;
        }
        measurementData.carrierFrequencyHz += CarrierFrequencies[measurementData.svType];
        measurementData.flags |= GNSS_MEASUREMENTS_DATA_CARRIER_FREQUENCY_BIT;

        LOC_LOGv("gnss_measurement_report_ptr.gnssSignalType_valid = 0");
    }

    // accumulatedDeltaRangeM
    if (gnss_measurement_info.validMask & QMI_LOC_SV_CARRIER_PHASE_VALID_V02) {
        measurementData.carrierPhase = gnss_measurement_info.carrierPhase;
        measurementData.flags |= GNSS_MEASUREMENTS_DATA_CARRIER_PHASE_BIT;
        if ((validMeasStatus & QMI_LOC_MASK_MEAS_STATUS_LP_VALID_V02) &&
            (validMeasStatus & QMI_LOC_MASK_MEAS_STATUS_LP_POS_VALID_V02)) {
            measurementData.carrierPhase += 0.5;
        }
        measurementData.adrMeters =
            (SPEED_OF_LIGHT / measurementData.carrierFrequencyHz) * measurementData.carrierPhase;
        LOC_LOGv("carrierPhase = %.2f adrMeters = %.2f",
                 measurementData.carrierPhase,
                 measurementData.adrMeters);
    } else {
        measurementData.adrMeters = 0.0;
    }

    // carrierPhaseUncertainty
    if (1 == svMeas.carrierPhaseUncValid) {
        measurementData.carrierPhaseUncertainty = svMeas.carrierPhaseUnc;
        measurementData.flags |= GNSS_MEASUREMENTS_DATA_CARRIER_PHASE_UNCERTAINTY_BIT;
    }

    // accumulatedDeltaRangeUncertaintyM
    if (!isExt) {
        if (gnss_measurement_report_ptr.svCarrierPhaseUncertainty_valid) {
            measurementData.adrUncertaintyMeters =
                (SPEED_OF_LIGHT / measurementData.carrierFrequencyHz) *
                gnss_measurement_report_ptr.svCarrierPhaseUncertainty[index];
            LOC_LOGv("carrierPhaseUnc = %.6f adrMetersUnc = %.6f",
                     gnss_measurement_report_ptr.svCarrierPhaseUncertainty[index],
                     measurementData.adrUncertaintyMeters);
        } else {
            measurementData.adrUncertaintyMeters = 0.0;
        }
    } else {
        if (gnss_measurement_report_ptr.extSvCarrierPhaseUncertainty_valid) {
            measurementData.adrUncertaintyMeters =
                (SPEED_OF_LIGHT / measurementData.carrierFrequencyHz) *
                gnss_measurement_report_ptr.extSvCarrierPhaseUncertainty[index];
            LOC_LOGv("extCarrierPhaseUnc = %.6f adrMetersUnc = %.6f",
                     gnss_measurement_report_ptr.extSvCarrierPhaseUncertainty[index],
                     measurementData.adrUncertaintyMeters);
        } else {
            measurementData.adrUncertaintyMeters = 0.0;
        }
    }

    // accumulatedDeltaRangeState
    measurementData.adrStateMask = GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_UNKNOWN;
    if ((gnss_measurement_info.validMask & QMI_LOC_SV_CARRIER_PHASE_VALID_V02) &&
        (gnss_measurement_info.carrierPhase != 0.0)) {
        measurementData.adrStateMask = GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_VALID_BIT;

        bool bFound = false;
        adrData tempAdrData;
        vector<adrData>::iterator it;
        // check the prior epoch
        // first see if info for this satellite exists in the vector (from prior epoch)
        for (it = mADRdata.begin(); it != mADRdata.end(); ++it) {
            tempAdrData = *it;
            if (gnss_measurement_report_ptr.system == tempAdrData.system &&
                ((gnss_measurement_report_ptr.gnssSignalType_valid &&
                (gnss_measurement_report_ptr.gnssSignalType == tempAdrData.gnssSignalType)) ||
                 (!gnss_measurement_report_ptr.gnssSignalType_valid &&
                    (0 == tempAdrData.gnssSignalType))) &&
                gnss_measurement_info.gnssSvId == tempAdrData.gnssSvId) {
                bFound = true;
                break;
            }
        }
        measurementData.adrStateMask |= GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_RESET_BIT;
        if (bFound) {
            LOC_LOGv("Found the carrier phase for this satellite from last epoch");
            if (tempAdrData.validMask & QMI_LOC_SV_CARRIER_PHASE_VALID_V02) {
                LOC_LOGv("and it has valid carrier phase");
                // let's make sure this is prior measurement
                if (mMinInterval <= 1000 &&
                    (tempAdrData.counter == (mCounter - 1))) {
                    // at this point prior epoch does have carrier phase valid
                    measurementData.adrStateMask &=
                            ~GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_RESET_BIT;
                    if (tempAdrData.validMask & QMI_LOC_SV_CYCLESLIP_COUNT_VALID_V02 &&
                        gnss_measurement_info.validMask & QMI_LOC_SV_CYCLESLIP_COUNT_VALID_V02) {
                        LOC_LOGv("cycle slip count is valid for both current and prior epochs");
                        if (tempAdrData.cycleSlipCount != gnss_measurement_info.cycleSlipCount) {
                            LOC_LOGv("cycle slip count for current epoch (%d)"
                                     " is different than the last epoch(%d)",
                                     gnss_measurement_info.cycleSlipCount,
                                     tempAdrData.cycleSlipCount);
                            measurementData.adrStateMask |=
                                    GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_CYCLE_SLIP_BIT;
                        }
                    }
                }
            }
            // now update the current satellite info to the vector
            tempAdrData.counter = mCounter;
            tempAdrData.validMask = gnss_measurement_info.validMask;
            tempAdrData.cycleSlipCount = gnss_measurement_info.cycleSlipCount;
            *it = tempAdrData;
        } else {
            // now add the current satellite info to the vector
            tempAdrData.counter = mCounter;
            tempAdrData.system = gnss_measurement_report_ptr.system;
            if (gnss_measurement_report_ptr.gnssSignalType_valid) {
                tempAdrData.gnssSignalType = gnss_measurement_report_ptr.gnssSignalType;
            } else {
                tempAdrData.gnssSignalType = 0;
            }
            tempAdrData.gnssSvId = gnss_measurement_info.gnssSvId;
            tempAdrData.validMask = gnss_measurement_info.validMask;
            tempAdrData.cycleSlipCount = gnss_measurement_info.cycleSlipCount;
            mADRdata.push_back(tempAdrData);
        }

        if (validMeasStatus & QMI_LOC_MASK_MEAS_STATUS_LP_VALID_V02) {
            LOC_LOGv("measurement status has QMI_LOC_MASK_MEAS_STATUS_LP_VALID_V02 set");
            measurementData.adrStateMask |=
                    GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_HALF_CYCLE_RESOLVED_BIT;
        }
        LOC_LOGv("adrStateMask = 0x%02x", measurementData.adrStateMask);
    }

    // cycleSlipCount
    if (1 == svMeas.cycleSlipCountValid) {
        measurementData.cycleSlipCount = svMeas.cycleSlipCount;
        measurementData.flags |= GNSS_MEASUREMENTS_DATA_CYCLE_SLIP_COUNT_BIT;
    }

    // multipath_indicator
    measurementData.multipathIndicator = GNSS_MEASUREMENTS_MULTIPATH_INDICATOR_UNKNOWN;

    // AGC
    if (gnss_measurement_report_ptr.jammerIndicator_valid) {
        if (GNSS_INVALID_JAMMER_IND !=
            gnss_measurement_report_ptr.jammerIndicator.agcMetricDb) {
            LOC_LOGv("AGC is valid: agcMetricDb = 0x%X bpMetricDb = 0x%X",
                gnss_measurement_report_ptr.jammerIndicator.agcMetricDb,
                gnss_measurement_report_ptr.jammerIndicator.bpMetricDb);

            measurementData.agcLevelDb =
                (double)gnss_measurement_report_ptr.jammerIndicator.agcMetricDb / 100.0;
            measurementData.flags |= GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT;
        } else {
            LOC_LOGv("AGC is invalid: agcMetricDb = 0x%X bpMetricDb = 0x%X",
                 gnss_measurement_report_ptr.jammerIndicator.agcMetricDb,
                 gnss_measurement_report_ptr.jammerIndicator.bpMetricDb);
        }
        bAgcIsPresent = true;
    } else {
        LOC_LOGv("AGC is not present");
        bAgcIsPresent = false;
    }

    // code type
    if (gnss_measurement_report_ptr.measurementCodeType_valid) {
        switch (gnss_measurement_report_ptr.measurementCodeType)
        {
        case eQMI_LOC_GNSS_CODE_TYPE_A_V02:
            measurementData.codeType = GNSS_MEASUREMENTS_CODE_TYPE_A; break;
        case eQMI_LOC_GNSS_CODE_TYPE_B_V02:
            measurementData.codeType = GNSS_MEASUREMENTS_CODE_TYPE_B; break;
        case eQMI_LOC_GNSS_CODE_TYPE_C_V02:
            measurementData.codeType = GNSS_MEASUREMENTS_CODE_TYPE_C; break;
        case eQMI_LOC_GNSS_CODE_TYPE_I_V02:
            measurementData.codeType = GNSS_MEASUREMENTS_CODE_TYPE_I; break;
        case eQMI_LOC_GNSS_CODE_TYPE_L_V02:
            measurementData.codeType = GNSS_MEASUREMENTS_CODE_TYPE_L; break;
        case eQMI_LOC_GNSS_CODE_TYPE_M_V02:
            measurementData.codeType = GNSS_MEASUREMENTS_CODE_TYPE_M; break;
        case eQMI_LOC_GNSS_CODE_TYPE_P_V02:
            measurementData.codeType = GNSS_MEASUREMENTS_CODE_TYPE_P; break;
        case eQMI_LOC_GNSS_CODE_TYPE_Q_V02:
            measurementData.codeType = GNSS_MEASUREMENTS_CODE_TYPE_Q; break;
        case eQMI_LOC_GNSS_CODE_TYPE_S_V02:
            measurementData.codeType = GNSS_MEASUREMENTS_CODE_TYPE_S; break;
        case eQMI_LOC_GNSS_CODE_TYPE_W_V02:
            measurementData.codeType = GNSS_MEASUREMENTS_CODE_TYPE_W; break;
        case eQMI_LOC_GNSS_CODE_TYPE_X_V02:
            measurementData.codeType = GNSS_MEASUREMENTS_CODE_TYPE_X; break;
        case eQMI_LOC_GNSS_CODE_TYPE_Y_V02:
            measurementData.codeType = GNSS_MEASUREMENTS_CODE_TYPE_Y; break;
        case eQMI_LOC_GNSS_CODE_TYPE_Z_V02:
            measurementData.codeType = GNSS_MEASUREMENTS_CODE_TYPE_Z; break;
        case eQMI_LOC_GNSS_CODE_TYPE_N_V02:
            measurementData.codeType = GNSS_MEASUREMENTS_CODE_TYPE_N; break;
        default:
            measurementData.codeType = GNSS_MEASUREMENTS_CODE_TYPE_OTHER; break;
        }
    } else {
        measurementData.codeType = GNSS_MEASUREMENTS_CODE_TYPE_OTHER;
    }

    memset(measurementData.otherCodeTypeName, 0, GNSS_MAX_NAME_LENGTH);
    if (GNSS_MEASUREMENTS_CODE_TYPE_OTHER == measurementData.codeType) {
        if (gnss_measurement_report_ptr.otherCodeTypeName_valid) {
            strlcpy(measurementData.otherCodeTypeName,
                    gnss_measurement_report_ptr.otherCodeTypeName,
                    std::min((uint32_t)sizeof(measurementData.otherCodeTypeName),
                             (uint32_t)gnss_measurement_report_ptr.otherCodeTypeName_len+1));
            LOC_LOGv("measurementData.otherCodeTypeName = %s", measurementData.otherCodeTypeName);
        }
    }

    // basebandCarrierToNoiseDbHz
    measurementData.basebandCarrierToNoiseDbHz = 0.0;
    if (measurementData.carrierToNoiseDbHz > gnss_measurement_info.gloRfLoss / 10.0) {
        measurementData.basebandCarrierToNoiseDbHz = measurementData.carrierToNoiseDbHz -
                gnss_measurement_info.gloRfLoss / 10.0;
    }

    // intersignal bias
    if (gnss_measurement_report_ptr.gnssSignalType_valid &&
        (gnss_measurement_report_ptr.systemTime_valid ||
         gnss_measurement_report_ptr.gloTime_valid)) {
        measurementData.gnssSignalType =
                convertQmiGnssSignalType(gnss_measurement_report_ptr.gnssSignalType);
    }

    LOC_LOGv(" GNSS measurement raw data received from modem:\n"
             " Input => gnssSvId=%d validMask=0x%04x validMeasStatus=0x%" PRIx64
             "  CNo=%d gloRfLoss=%d dopplerShift=%.2f dopplerShiftUnc=%.2f"
             "  fineSpeed=%.2f fineSpeedUnc=%.2f"
             "  svTimeMs=%u svTimeSubMs=%.2f svTimeUncMs=%.2f codeType=%d"
             "  carrierPhase=%.2f carrierPhaseUnc=%.6f cycleSlipCount=%u\n"
             " GNSS measurement data after conversion:"
             " Output => size=%" PRIu32 "svid=%d time_offset_ns=%.2f stateMask=0x%08x"
             "  received_sv_time_in_ns=%" PRIu64 " received_sv_time_uncertainty_in_ns=%" PRIu64
             "  c_n0_dbhz=%.2f baseband_c_n0_dbhz=%.2f"
             "  pseudorange_rate_mps=%.2f pseudorange_rate_uncertainty_mps=%.2f"
             "  adrStateMask=0x%02x adrMeters=%.2f adrUncertaintyMeters=%.6f"
             "  carrierFrequencyHz=%.2f codeType=%d",
             gnss_measurement_info.gnssSvId,                                    // %d
             gnss_measurement_info.validMask,                                   // 0x%4x
             validMeasStatus,                                                   // %PRIx64
             gnss_measurement_info.CNo,                                         // %d
             gnss_measurement_info.gloRfLoss,                                   // %d
             gnss_measurement_info.svTimeSpeed.dopplerShift,                    // %f
             gnss_measurement_info.svTimeSpeed.dopplerShiftUnc,                 // %f
             gnss_measurement_info.fineSpeed,                                   // %f
             gnss_measurement_info.fineSpeedUnc,                                // %f
             gnss_measurement_info.svTimeSpeed.svTimeMs,                        // %u
             gnss_measurement_info.svTimeSpeed.svTimeSubMs,                     // %f
             gnss_measurement_info.svTimeSpeed.svTimeUncMs,                     // %f
             gnss_measurement_report_ptr.measurementCodeType,                   // %d
             gnss_measurement_info.carrierPhase,                                // %f
             gnss_measurement_report_ptr.svCarrierPhaseUncertainty[index],      // %f
             gnss_measurement_info.cycleSlipCount,                              // %u
             measurementData.size,                                              // %zu
             measurementData.svId,                                              // %d
             measurementData.timeOffsetNs,                                      // %f
             measurementData.stateMask,                                         // 0x%8x
             measurementData.receivedSvTimeNs,                                  // %PRIu64
             measurementData.receivedSvTimeUncertaintyNs,                       // %PRIu64
             measurementData.carrierToNoiseDbHz,                                // %g
             measurementData.basebandCarrierToNoiseDbHz,                        // %g
             measurementData.pseudorangeRateMps,                                // %g
             measurementData.pseudorangeRateUncertaintyMps,                     // %g
             measurementData.adrStateMask,                                      // 0x%2x
             measurementData.adrMeters,                                         // %f
             measurementData.adrUncertaintyMeters,                              // %f
             measurementData.carrierFrequencyHz,                                // %f
             measurementData.codeType);                                         // %d
    return bAgcIsPresent;
}

/*convert GnssMeasurementsClock type from QMI LOC to loc eng format*/
int LocApiV02 :: convertGnssClock (GnssMeasurementsClock& clock,
    const qmiLocEventGnssSvMeasInfoIndMsgT_v02& gnss_measurement_info)
{
    static uint32_t oldRefFCount = 0;
    static uint32_t newRefFCount = 0;
    static uint32_t oldDiscCount = 0;
    static uint32_t newDiscCount = 0;
    static uint32_t localDiscCount = 0;
    int msInWeek = -1;

    LOC_LOGV ("%s:%d]: entering\n", __func__, __LINE__);

    // size
    clock.size = sizeof(GnssMeasurementsClock);

    // flag initiation
    GnssMeasurementsClockFlagsMask flags = 0;

    if (gnss_measurement_info.systemTimeExt_valid &&
        gnss_measurement_info.numClockResets_valid) {
        newRefFCount = gnss_measurement_info.systemTimeExt.refFCount;
        newDiscCount = gnss_measurement_info.numClockResets;
        if ((true == mMeasurementsStarted) ||
            (oldDiscCount != newDiscCount) ||
            (newRefFCount <= oldRefFCount))
        {
            if (true == mMeasurementsStarted)
            {
                mMeasurementsStarted = false;
            }
            // do not increment in full power mode
            if (GNSS_POWER_MODE_M1 != mPowerMode) {
                localDiscCount++;
            }
        }
        oldDiscCount = newDiscCount;
        oldRefFCount = newRefFCount;

        // timeNs & timeUncertaintyNs
        clock.timeNs = (int64_t)gnss_measurement_info.systemTimeExt.refFCount * 1e6;
        clock.hwClockDiscontinuityCount = localDiscCount;
        clock.timeUncertaintyNs = 0.0;

        msInWeek = (int)gnss_measurement_info.systemTime.systemMsec;
        if (gnss_measurement_info.systemTime_valid) {
            uint16_t systemWeek = gnss_measurement_info.systemTime.systemWeek;
            uint32_t systemMsec = gnss_measurement_info.systemTime.systemMsec;
            float sysClkBias = gnss_measurement_info.systemTime.systemClkTimeBias;
            float sysClkUncMs = gnss_measurement_info.systemTime.systemClkTimeUncMs;
            bool isTimeValid = (sysClkUncMs <= 16.0f); // 16ms

            if (systemWeek != C_GPS_WEEK_UNKNOWN && isTimeValid) {
                // fullBiasNs, biasNs & biasUncertaintyNs
                int64_t totalMs = ((int64_t)systemWeek) *
                                  ((int64_t)WEEK_MSECS) + ((int64_t)systemMsec);
                int64_t gpsTimeNs = totalMs * 1000000 - (int64_t)(sysClkBias * 1e6);
                clock.fullBiasNs = clock.timeNs - gpsTimeNs;
                clock.biasNs = sysClkBias * 1e6 - (double)((int64_t)(sysClkBias * 1e6));
                clock.biasUncertaintyNs = (double)sysClkUncMs * 1e6;
                flags |= (GNSS_MEASUREMENTS_CLOCK_FLAGS_FULL_BIAS_BIT |
                          GNSS_MEASUREMENTS_CLOCK_FLAGS_BIAS_BIT |
                          GNSS_MEASUREMENTS_CLOCK_FLAGS_BIAS_UNCERTAINTY_BIT);

                if (mGnssMeasurements->gnssSvMeasurementSet.svMeasSetHeader.flags &
                    GNSS_SV_MEAS_HEADER_HAS_LEAP_SECOND) {
                    clock.leapSecond = mGnssMeasurements->
                            gnssSvMeasurementSet.svMeasSetHeader.leapSec.leapSec;
                    flags |= GNSS_MEASUREMENTS_CLOCK_FLAGS_LEAP_SECOND_BIT;
                    LOC_LOGV("clock.leapSecond: %d", clock.leapSecond);
                } else {
                    LOC_LOGV("GNSS_SV_MEAS_HEADER_HAS_LEAP_SECOND is not set");
                }
            }
        }
    }

    // driftNsps & driftUncertaintyNsps
    if (gnss_measurement_info.rcvrClockFrequencyInfo_valid)
    {
        double driftMPS = gnss_measurement_info.rcvrClockFrequencyInfo.clockDrift;
        double driftUncMPS = gnss_measurement_info.rcvrClockFrequencyInfo.clockDriftUnc;

        clock.driftNsps = driftMPS * MPS_TO_NSPS;
        clock.driftUncertaintyNsps = driftUncMPS * MPS_TO_NSPS;

        flags |= (GNSS_MEASUREMENTS_CLOCK_FLAGS_DRIFT_BIT |
                  GNSS_MEASUREMENTS_CLOCK_FLAGS_DRIFT_UNCERTAINTY_BIT);
    }

    // referenceSignalTypeForIsb
    clock.referenceSignalTypeForIsb.svType = GNSS_SV_TYPE_GPS;
    clock.referenceSignalTypeForIsb.carrierFrequencyHz = GPS_L1CA_CARRIER_FREQUENCY;
    clock.referenceSignalTypeForIsb.codeType = GNSS_MEASUREMENTS_CODE_TYPE_C;
    clock.referenceSignalTypeForIsb.otherCodeTypeName[0] = '\0';

    clock.flags = flags;

    LOC_LOGV(" %s:%d]: GNSS measurement clock data received from modem: \n", __func__, __LINE__);
    LOC_LOGV(" Input => systemTime_valid=%d systemTimeExt_valid=%d numClockResets_valid=%d\n",
             gnss_measurement_info.systemTime_valid,                      // %d
             gnss_measurement_info.systemTimeExt_valid,                   // %d
        gnss_measurement_info.numClockResets_valid);                 // %d

    LOC_LOGV("  systemWeek=%d systemMsec=%d systemClkTimeBias=%f\n",
             gnss_measurement_info.systemTime.systemWeek,                 // %d
             gnss_measurement_info.systemTime.systemMsec,                 // %d
        gnss_measurement_info.systemTime.systemClkTimeBias);         // %f

    LOC_LOGV("  systemClkTimeUncMs=%f refFCount=%d numClockResets=%d\n",
             gnss_measurement_info.systemTime.systemClkTimeUncMs,         // %f
        gnss_measurement_info.systemTimeExt.refFCount,               // %d
        gnss_measurement_info.numClockResets);                       // %d

    LOC_LOGV("  clockDrift=%f clockDriftUnc=%f\n",
        gnss_measurement_info.rcvrClockFrequencyInfo.clockDrift,     // %f
        gnss_measurement_info.rcvrClockFrequencyInfo.clockDriftUnc); // %f


    LOC_LOGV(" %s:%d]: GNSS measurement clock after conversion: \n", __func__, __LINE__);
    LOC_LOGV(" Output => timeNs=%" PRId64 "\n",
        clock.timeNs);                       // %PRId64

    LOC_LOGV("  fullBiasNs=%" PRId64 " biasNs=%g bias_uncertainty_ns=%g\n",
        clock.fullBiasNs,                    // %PRId64
        clock.biasNs,                        // %g
        clock.biasUncertaintyNs);            // %g

    LOC_LOGV("  driftNsps=%g drift_uncertainty_nsps=%g\n",
        clock.driftNsps,                     // %g
        clock.driftUncertaintyNsps);         // %g

    LOC_LOGV("  hw_clock_discontinuity_count=%d flags=0x%04x\n",
        clock.hwClockDiscontinuityCount,     // %lld
        clock.flags);                        // %04x

    return msInWeek;
}

/* event callback registered with the loc_api v02 interface */
void LocApiV02 :: eventCb(locClientHandleType /*clientHandle*/,
  uint32_t eventId, locClientEventIndUnionType eventPayload)
{
  LOC_LOGd("event id = 0x%X", eventId);

  switch(eventId)
  {
    //Position Report
    case QMI_LOC_EVENT_POSITION_REPORT_IND_V02:
      reportPosition(eventPayload.pPositionReportEvent);
      break;

    // Satellite report
    case QMI_LOC_EVENT_GNSS_SV_INFO_IND_V02:
      reportSv(eventPayload.pGnssSvInfoReportEvent);
      break;

    // Status report
    case QMI_LOC_EVENT_ENGINE_STATE_IND_V02:
      reportEngineState(eventPayload.pEngineState);
      break;

    case QMI_LOC_EVENT_FIX_SESSION_STATE_IND_V02:
      reportFixSessionState(eventPayload.pFixSessionState);
      break;

    // NMEA
    case QMI_LOC_EVENT_NMEA_IND_V02:
      reportNmea(eventPayload.pNmeaReportEvent);
      break;

    // XTRA request
    case QMI_LOC_EVENT_INJECT_PREDICTED_ORBITS_REQ_IND_V02:
      LOC_LOGD("%s:%d]: XTRA download request\n", __func__,
                    __LINE__);
      reportXtraServerUrl(eventPayload.pInjectPredictedOrbitsReqEvent);
      requestXtraData();
      break;

    // time request
    case QMI_LOC_EVENT_INJECT_TIME_REQ_IND_V02:
      LOC_LOGD("%s:%d]: Time request\n", __func__,
                    __LINE__);
      requestTime();
      break;

    //position request
    case QMI_LOC_EVENT_INJECT_POSITION_REQ_IND_V02:
      LOC_LOGD("%s:%d]: Position request\n", __func__,
                    __LINE__);
      requestLocation();
      break;

    // NI request
    case QMI_LOC_EVENT_NI_NOTIFY_VERIFY_REQ_IND_V02:
      reportNiRequest(eventPayload.pNiNotifyVerifyReqEvent);
      break;

    // AGPS connection request
    case QMI_LOC_EVENT_LOCATION_SERVER_CONNECTION_REQ_IND_V02:
      reportAtlRequest(eventPayload.pLocationServerConnReqEvent);
      break;

    case QMI_LOC_EVENT_GNSS_MEASUREMENT_REPORT_IND_V02:
      LOC_LOGd("GNSS Measurement Report");
      if (mInSession) {
          reportGnssMeasurementData(*eventPayload.pGnssSvRawInfoEvent);
      }
      break;

    case QMI_LOC_EVENT_SV_POLYNOMIAL_REPORT_IND_V02:
      LOC_LOGD("%s:%d]: GNSS SV Polynomial Ind\n", __func__,
               __LINE__);
      reportSvPolynomial(eventPayload.pGnssSvPolyInfoEvent);
      break;

    case QMI_LOC_EVENT_GPS_EPHEMERIS_REPORT_IND_V02:
    case QMI_LOC_EVENT_GLONASS_EPHEMERIS_REPORT_IND_V02:
    case QMI_LOC_EVENT_BDS_EPHEMERIS_REPORT_IND_V02:
    case QMI_LOC_EVENT_GALILEO_EPHEMERIS_REPORT_IND_V02:
    case QMI_LOC_EVENT_QZSS_EPHEMERIS_REPORT_IND_V02:
      reportSvEphemeris(eventId, eventPayload);
      break;

    //Unpropagated position report
    case QMI_LOC_EVENT_UNPROPAGATED_POSITION_REPORT_IND_V02:
      reportPosition(eventPayload.pPositionReportEvent, true);
      break;

    case QMI_LOC_GET_BLACKLIST_SV_IND_V02:
      LOC_LOGd("GET blacklist SV Ind");
      reportGnssSvIdConfig(*eventPayload.pGetBlacklistSvEvent);
      break;

    case QMI_LOC_GET_CONSTELLATION_CONTROL_IND_V02:
      LOC_LOGd("GET constellation Ind");
      reportGnssSvTypeConfig(*eventPayload.pGetConstellationConfigEvent);
      break;

    case  QMI_LOC_EVENT_WIFI_REQ_IND_V02:
      LOC_LOGd("WIFI Req Ind");
      requestOdcpi(*eventPayload.pWifiReqEvent);
      break;

    case QMI_LOC_EVENT_REPORT_IND_V02:
      reportLocEvent(eventPayload.pLocEvent);
      break;

    // System info event regarding next leap second
    case QMI_LOC_SYSTEM_INFO_IND_V02:
      reportSystemInfo(eventPayload.pLocSystemInfoEvent);
      break;

    case QMI_LOC_LOCATION_REQUEST_NOTIFICATION_IND_V02:
      reportLocationRequestNotification(eventPayload.pLocReqNotifEvent);
      break;

    case QMI_LOC_EVENT_GEOFENCE_BREACH_NOTIFICATION_IND_V02:
      LOC_LOGd("Got QMI_LOC_EVENT_GEOFENCE_BREACH_NOTIFICATION_IND_V02");
      geofenceBreachEvent(eventPayload.pGeofenceBreachEvent);
      break;

    case QMI_LOC_EVENT_GEOFENCE_BATCHED_BREACH_NOTIFICATION_IND_V02:
      LOC_LOGd("Got QMI_LOC_EVENT_GEOFENCE_BATCHED_BREACH_NOTIFICATION_IND_V02");
      geofenceBreachEvent(eventPayload.pGeofenceBatchedBreachEvent);
      break;

    case QMI_LOC_EVENT_GEOFENCE_GEN_ALERT_IND_V02:
      geofenceStatusEvent(eventPayload.pGeofenceGenAlertEvent);
      break;

    case QMI_LOC_EVENT_GEOFENCE_BATCHED_DWELL_NOTIFICATION_IND_V02:
      LOC_LOGd("Got QMI_LOC_EVENT_GEOFENCE_BATCHED_DWELL_NOTIFICATION_IND_V02");
      geofenceDwellEvent(eventPayload.pGeofenceBatchedDwellEvent);
      break;

    case QMI_LOC_EVENT_BATCH_FULL_NOTIFICATION_IND_V02:
      LOC_LOGd("Got QMI_LOC_EVENT_BATCH_FULL_NOTIFICATION_IND_V02");
      batchFullEvent(eventPayload.pBatchCount);
      break;

    case QMI_LOC_EVENT_BATCHING_STATUS_IND_V02:
      LOC_LOGd("Got QMI_LOC_EVENT_BATCHING_STATUS_IND_V02");
      batchStatusEvent(eventPayload.pBatchingStatusEvent);
      break;

    case QMI_LOC_EVENT_DBT_POSITION_REPORT_IND_V02:
      LOC_LOGd("Got QMI_LOC_EVENT_DBT_POSITION_REPORT_IND_V02");
      onDbtPosReportEvent(eventPayload.pDbtPositionReportEvent);
      break;

    case QMI_LOC_LATENCY_INFORMATION_IND_V02:
      reportLatencyInfo(eventPayload.pLocLatencyInfoIndMsg);
      break;

  }
}

/* Call the service LocAdapterBase down event*/
void LocApiV02 :: errorCb(locClientHandleType /*handle*/,
                             locClientErrorEnumType errorId)
{
  if(errorId == eLOC_CLIENT_ERROR_SERVICE_UNAVAILABLE)
  {
    LOC_LOGE("%s:%d]: Service unavailable error\n",
                  __func__, __LINE__);

    handleEngineDownEvent();
  }
}

void LocApiV02 ::getWwanZppFix()
{
    sendMsg(new LocApiMsg([this] () {

    locClientReqUnionType req_union;
    qmiLocGetAvailWwanPositionReqMsgT_v02 zpp_req;
    memset(&zpp_req, 0, sizeof(zpp_req));

    req_union.pGetAvailWwanPositionReq = &zpp_req;

    LOC_LOGD("%s:%d]: Get ZPP Fix from available wwan position\n", __func__, __LINE__);
    locClientStatusEnumType status =
            locClientSendReq(QMI_LOC_GET_AVAILABLE_WWAN_POSITION_REQ_V02, req_union);

    if (status != eLOC_CLIENT_SUCCESS) {
        LOC_LOGe("error! status = %s\n", loc_get_v02_client_status_name(status));
    }
    }));
}

void LocApiV02 ::getBestAvailableZppFix()
{
    sendMsg(new LocApiMsg([this] () {

    locClientReqUnionType req_union;
    qmiLocGetBestAvailablePositionReqMsgT_v02 zpp_req;

    memset(&zpp_req, 0, sizeof(zpp_req));
    req_union.pGetBestAvailablePositionReq = &zpp_req;

    LOC_LOGd("Get ZPP Fix from best available source\n");

    locClientStatusEnumType status =
            locClientSendReq(QMI_LOC_GET_BEST_AVAILABLE_POSITION_REQ_V02, req_union);

    if (status != eLOC_CLIENT_SUCCESS) {
        LOC_LOGe("error! status = %s\n", loc_get_v02_client_status_name(status));
    }
    }));
}

LocationError LocApiV02 :: setGpsLockSync(GnssConfigGpsLock lock)
{
    LocationError err = LOCATION_ERROR_SUCCESS;
    qmiLocSetEngineLockReqMsgT_v02 setEngineLockReq;
    qmiLocSetEngineLockIndMsgT_v02 setEngineLockInd;
    locClientStatusEnumType status;
    locClientReqUnionType req_union;

    memset(&setEngineLockReq, 0, sizeof(setEngineLockReq));
    setEngineLockReq.lockType = convertGpsLockFromAPItoQMI((GnssConfigGpsLock)lock);;
    setEngineLockReq.subType_valid = true;
    setEngineLockReq.subType = eQMI_LOC_LOCK_ALL_SUB_V02;
    setEngineLockReq.lockClient_valid = false;
    req_union.pSetEngineLockReq = &setEngineLockReq;
    LOC_LOGd("API lock type = 0x%X QMI lockType = %d", lock, setEngineLockReq.lockType);
    memset(&setEngineLockInd, 0, sizeof(setEngineLockInd));
    status = locSyncSendReq(QMI_LOC_SET_ENGINE_LOCK_REQ_V02,
                            req_union, LOC_ENGINE_SYNC_REQUEST_LONG_TIMEOUT,
                            QMI_LOC_SET_ENGINE_LOCK_IND_V02,
                            &setEngineLockInd);
    if (eLOC_CLIENT_SUCCESS != status || eQMI_LOC_SUCCESS_V02 != setEngineLockInd.status) {
        LOC_LOGe("Set engine lock failed. status: %s, ind status:%s",
            loc_get_v02_client_status_name(status),
            loc_get_v02_qmi_status_name(setEngineLockInd.status));
        err = LOCATION_ERROR_GENERAL_FAILURE;
    }
    return err;
}

void LocApiV02::requestForAidingData(GnssAidingDataSvMask svDataMask)
{
    sendMsg(new LocApiMsg([this, svDataMask] () {
        locClientEventMaskType qmiMask = 0;

        if (svDataMask & GNSS_AIDING_DATA_SV_POLY_BIT)
            qmiMask |= QMI_LOC_EVENT_MASK_GNSS_SV_POLYNOMIAL_REPORT_V02;

        if (svDataMask & GNSS_AIDING_DATA_SV_EPHEMERIS_BIT)
            qmiMask |= QMI_LOC_EVENT_MASK_EPHEMERIS_REPORT_V02;

        if (svDataMask & GNSS_AIDING_DATA_SV_IONOSPHERE_BIT)
            qmiMask |= QMI_LOC_EVENT_MASK_GNSS_EVENT_REPORT_V02;

        sendRequestForAidingData(qmiMask);
    }));
}

/*
  Returns
  Current value of GPS Lock on success
  -1 on failure
*/
int LocApiV02 :: getGpsLock(uint8_t subType)
{
    qmiLocGetEngineLockReqMsgT_v02 getEngineLockReq;
    qmiLocGetEngineLockIndMsgT_v02 getEngineLockInd;
    locClientStatusEnumType status;
    locClientReqUnionType req_union;
    int ret=0;
    memset(&getEngineLockInd, 0, sizeof(getEngineLockInd));

    //Passing req_union as a parameter even though this request has no payload
    //since NULL or 0 gives an error during compilation
    getEngineLockReq.subType_valid = true;
    getEngineLockReq.subType = (qmiLocLockSubInfoEnumT_v02)subType;
    req_union.pGetEngineLockReq = &getEngineLockReq;
    status = locSyncSendReq(QMI_LOC_GET_ENGINE_LOCK_REQ_V02,
                            req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT,
                            QMI_LOC_GET_ENGINE_LOCK_IND_V02,
                            &getEngineLockInd);
    if(status != eLOC_CLIENT_SUCCESS || getEngineLockInd.status != eQMI_LOC_SUCCESS_V02) {
        LOC_LOGE("%s:%d]: Set engine lock failed. status: %s, ind status:%s\n",
                 __func__, __LINE__,
                 loc_get_v02_client_status_name(status),
                 loc_get_v02_qmi_status_name(getEngineLockInd.status));
        ret = -1;
    }
    else {
        if(getEngineLockInd.lockType_valid) {
            ret = (int)convertGpsLockFromQMItoAPI(getEngineLockInd.lockType);
        }
        else {
            LOC_LOGE("%s:%d]: Lock Type not valid\n", __func__, __LINE__);
            ret = -1;
        }
    }
    return ret;
}

LocationError
LocApiV02:: setXtraVersionCheckSync(uint32_t check)
{
    LocationError err = LOCATION_ERROR_SUCCESS;
    qmiLocSetXtraVersionCheckReqMsgT_v02 req;
    qmiLocSetXtraVersionCheckIndMsgT_v02 ind;
    locClientStatusEnumType status;
    locClientReqUnionType req_union;

    LOC_LOGD("%s:%d]: Enter. check: %u", __func__, __LINE__, check);
    memset(&req, 0, sizeof(req));
    memset(&ind, 0, sizeof(ind));
    switch (check) {
    case 0:
        req.xtraVersionCheckMode = eQMI_LOC_XTRA_VERSION_CHECK_DISABLE_V02;
        break;
    case 1:
        req.xtraVersionCheckMode = eQMI_LOC_XTRA_VERSION_CHECK_AUTO_V02;
        break;
    case 2:
        req.xtraVersionCheckMode = eQMI_LOC_XTRA_VERSION_CHECK_XTRA2_V02;
        break;
    case 3:
        req.xtraVersionCheckMode = eQMI_LOC_XTRA_VERSION_CHECK_XTRA3_V02;
        break;
    default:
        req.xtraVersionCheckMode = eQMI_LOC_XTRA_VERSION_CHECK_DISABLE_V02;
        break;
    }

    req_union.pSetXtraVersionCheckReq = &req;
    status = locSyncSendReq(QMI_LOC_SET_XTRA_VERSION_CHECK_REQ_V02,
                            req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT,
                            QMI_LOC_SET_XTRA_VERSION_CHECK_IND_V02,
                            &ind);
    if(status != eLOC_CLIENT_SUCCESS || ind.status != eQMI_LOC_SUCCESS_V02) {
        LOC_LOGE("%s:%d]: Set xtra version check failed. status: %s, ind status:%s\n",
                 __func__, __LINE__,
                 loc_get_v02_client_status_name(status),
                 loc_get_v02_qmi_status_name(ind.status));
        err = LOCATION_ERROR_GENERAL_FAILURE;
    }

    LOC_LOGD("%s:%d]: Exit. err: %u", __func__, __LINE__, err);
    return err;
}

int LocApiV02::setSvMeasurementConstellation(const locClientEventMaskType mask)
{
    enum loc_api_adapter_err ret_val = LOC_API_ADAPTER_ERR_SUCCESS;
    qmiLocSetGNSSConstRepConfigReqMsgT_v02 setGNSSConstRepConfigReq;
    qmiLocSetGNSSConstRepConfigIndMsgT_v02 setGNSSConstRepConfigInd;
    locClientStatusEnumType status;
    locClientReqUnionType req_union;

    qmiLocGNSSConstellEnumT_v02 svConstellation = eQMI_SYSTEM_GPS_V02 |
                                                eQMI_SYSTEM_GLO_V02 |
                                                eQMI_SYSTEM_BDS_V02 |
                                                eQMI_SYSTEM_GAL_V02 |
                                                eQMI_SYSTEM_QZSS_V02 |
                                                eQMI_SYSTEM_NAVIC_V02;
    LOC_LOGd("set GNSS measurement to report constellation: %" PRIx64 " "
            "report mask = 0x%" PRIx64 "\n", svConstellation, mask);

    memset(&setGNSSConstRepConfigReq, 0, sizeof(setGNSSConstRepConfigReq));

    setGNSSConstRepConfigReq.measReportConfig_valid = true;
    if ((mask & QMI_LOC_EVENT_MASK_GNSS_MEASUREMENT_REPORT_V02) ||
        mMasterRegisterNotSupported) {
        setGNSSConstRepConfigReq.measReportConfig = svConstellation;
    }

    setGNSSConstRepConfigReq.svPolyReportConfig_valid = true;
    if (mask & QMI_LOC_EVENT_MASK_GNSS_SV_POLYNOMIAL_REPORT_V02) {
        setGNSSConstRepConfigReq.svPolyReportConfig = svConstellation;
    }
    req_union.pSetGNSSConstRepConfigReq = &setGNSSConstRepConfigReq;
    memset(&setGNSSConstRepConfigInd, 0, sizeof(setGNSSConstRepConfigInd));

    status = locSyncSendReq(QMI_LOC_SET_GNSS_CONSTELL_REPORT_CONFIG_V02,
        req_union,
        LOC_ENGINE_SYNC_REQUEST_TIMEOUT,
        QMI_LOC_SET_GNSS_CONSTELL_REPORT_CONFIG_IND_V02,
        &setGNSSConstRepConfigInd);

    if (status != eLOC_CLIENT_SUCCESS ||
        (setGNSSConstRepConfigInd.status != eQMI_LOC_SUCCESS_V02 &&
            setGNSSConstRepConfigInd.status != eQMI_LOC_ENGINE_BUSY_V02)) {
        LOC_LOGE("%s:%d]: Set GNSS constellation failed. status: %s, ind status:%s\n",
            __func__, __LINE__,
            loc_get_v02_client_status_name(status),
            loc_get_v02_qmi_status_name(setGNSSConstRepConfigInd.status));
        ret_val = LOC_API_ADAPTER_ERR_GENERAL_FAILURE;
    }
    else {
        LOC_LOGD("%s:%d]: Set GNSS constellation succeeded.\n",
            __func__, __LINE__);
    }

    return ret_val;
}

void LocApiV02::setConstrainedTuncMode(bool enabled,
                                       float tuncConstraint,
                                       uint32_t energyBudget,
                                       LocApiResponse *adapterResponse) {
    sendMsg(new LocApiMsg([this, enabled, tuncConstraint, energyBudget, adapterResponse] () {

    LocationError err = LOCATION_ERROR_SUCCESS;
    qmiLocSetConstrainedTuncModeReqMsgT_v02 req;
    qmiLocSetConstrainedTuncModeIndMsgT_v02 ind;
    locClientStatusEnumType status;
    locClientReqUnionType req_union;

    memset(&req, 0, sizeof(req));
    memset(&ind, 0, sizeof(ind));
    req.tuncConstraintOn = enabled;
    if (tuncConstraint > 0.0) {
        req.tuncConstraint_valid = true;
        req.tuncConstraint = tuncConstraint;
    }
    if (energyBudget != 0) {
        req.energyBudget_valid = true;
        req.energyBudget = energyBudget;
    }

    LOC_LOGd("Enter. enabled %d, tuncConstraint (%d, %f),"
             "energyBudget (%d, %d)", req.tuncConstraintOn,
             req.tuncConstraint_valid, req.tuncConstraint,
             req.energyBudget_valid, req.energyBudget);

    req_union.pSetConstrainedTuncModeReq = &req;
    status = locSyncSendReq(QMI_LOC_SET_CONSTRAINED_TUNC_MODE_REQ_V02,
                            req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT,
                            QMI_LOC_SET_CONSTRAINED_TUNC_MODE_IND_V02,
                            &ind);
    if(status != eLOC_CLIENT_SUCCESS || ind.status != eQMI_LOC_SUCCESS_V02) {
        LOC_LOGe("failed, status: %s, ind status:%s\n",
                 loc_get_v02_client_status_name(status),
                 loc_get_v02_qmi_status_name(ind.status));
        err = LOCATION_ERROR_GENERAL_FAILURE;
    }

    if (adapterResponse) {
        adapterResponse->returnToSender(err);
    }
    LOC_LOGv("Exit. err: %u", err);
  }));
}

void LocApiV02::setPositionAssistedClockEstimatorMode
        (bool enabled, LocApiResponse *adapterResponse) {

    sendMsg(new LocApiMsg([this, enabled, adapterResponse] () {

    LocationError err = LOCATION_ERROR_SUCCESS;
    qmiLocEnablePositionAssistedClockEstReqMsgT_v02 req;
    qmiLocEnablePositionAssistedClockEstIndMsgT_v02 ind;
    locClientStatusEnumType status;
    locClientReqUnionType req_union;

    LOC_LOGd("Enter. enabled %d", enabled);
    memset(&req, 0, sizeof(req));
    memset(&ind, 0, sizeof(ind));
    req.enablePositionAssistedClockEst = enabled;

    req_union.pSetEnablePositionAssistedClockEstReq = &req;
    status = locSyncSendReq(QMI_LOC_ENABLE_POSITION_ASSISTED_CLOCK_EST_REQ_V02,
                            req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT,
                            QMI_LOC_ENABLE_POSITION_ASSISTED_CLOCK_EST_IND_V02,
                            &ind);
    if(status != eLOC_CLIENT_SUCCESS || ind.status != eQMI_LOC_SUCCESS_V02) {
        LOC_LOGe("failed. status: %s, ind status:%s\n",
                 loc_get_v02_client_status_name(status),
                 loc_get_v02_qmi_status_name(ind.status));
        err = LOCATION_ERROR_GENERAL_FAILURE;
    }
    if (adapterResponse) {
        adapterResponse->returnToSender(err);
    }
    LOC_LOGv("Exit. err: %u", err);
    }));
}

void LocApiV02::getGnssEnergyConsumed() {
    sendMsg(new LocApiMsg([this] {

    LocationError err = LOCATION_ERROR_SUCCESS;

    qmiLocQueryGNSSEnergyConsumedReqMsgT_v02 req;
    qmiLocQueryGNSSEnergyConsumedIndMsgT_v02 ind;
    locClientStatusEnumType status;
    locClientReqUnionType req_union;

    LOC_LOGd("Enter. ");
    memset(&req, 0, sizeof(req));
    memset(&ind, 0, sizeof(ind));

    req_union.pQueryGNSSEnergyConsumedReq = &req;
    status = locSyncSendReq(QMI_LOC_QUERY_GNSS_ENERGY_CONSUMED_REQ_V02,
                            req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT,
                            QMI_LOC_QUERY_GNSS_ENERGY_CONSUMED_IND_V02,
                            &ind);

    if(status != eLOC_CLIENT_SUCCESS) {
        LOC_LOGe("failed. status: %s\n", loc_get_v02_client_status_name(status));
        // report invalid read to indicate error (based on QMI message)
        LocApiBase::reportGnssEngEnergyConsumedEvent(0xffffffffffffffff);
        err = LOCATION_ERROR_GENERAL_FAILURE;
    } else {
        LocApiBase::reportGnssEngEnergyConsumedEvent(ind.energyConsumedSinceFirstBoot);
    }

    LOC_LOGd("Exit. err: %u", err);
    }));
}

void LocApiV02 :: updateSystemPowerState(PowerStateType powerState){
    sendMsg(new LocApiMsg([this, powerState] () {

    LocationError err = LOCATION_ERROR_SUCCESS;
    qmiLocInjectPlatformPowerStateReqMsgT_v02 req;
    qmiLocInjectPlatformPowerStateIndMsgT_v02 ind;

    locClientStatusEnumType status;
    locClientReqUnionType req_union;

    LOC_LOGd("Enter. power state %d", powerState);
    qmiLocPlatformPowerStateEnumT_v02 qmiPowerState = eQMI_LOC_POWER_STATE_UNKNOWN_V02;
    switch (powerState) {
    case POWER_STATE_SUSPEND:
        qmiPowerState = eQMI_LOC_POWER_STATE_SUSPENDED_V02;
        break;
    case POWER_STATE_RESUME:
        qmiPowerState = eQMI_LOC_POWER_STATE_RESUME_V02;
        break;
    case POWER_STATE_SHUTDOWN:
        qmiPowerState = eQMI_LOC_POWER_STATE_SHUTDOWN_V02;
        break;
    default:
        break;
    }

    // unknown power state will not be injected to modem
    if (eQMI_LOC_POWER_STATE_UNKNOWN_V02 != qmiPowerState) {
        memset(&req, 0, sizeof(req));
        memset(&ind, 0, sizeof(ind));
        req.powerState = qmiPowerState;
        req_union.pInjectPowerStateReq = &req;

        status = locSyncSendReq(QMI_LOC_INJECT_PLATFORM_POWER_STATE_REQ_V02,
                                req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT,
                                QMI_LOC_INJECT_PLATFORM_POWER_STATE_IND_V02,
                                &ind);
        if (status != eLOC_CLIENT_SUCCESS || ind.status != eQMI_LOC_SUCCESS_V02) {
            LOC_LOGe("failed. status: %s, ind status:%s\n",
                     loc_get_v02_client_status_name(status),
                     loc_get_v02_qmi_status_name(ind.status));
            err = LOCATION_ERROR_GENERAL_FAILURE;
        }
    }

    LOC_LOGd("Exit. err: %u", err);
    }));
}

void LocApiV02::reportLatencyInfo(const qmiLocLatencyInformationIndMsgT_v02* pLocLatencyInfo)
{
    GnssLatencyInfo gnssLatencyInfo = {};

    if (nullptr == pLocLatencyInfo) {
        LOC_LOGe("pLocLatencyInfo is nullptr");
        return;
    }

    if (eQMI_LOC_LATENCY_INFO_TYPE_MEASUREMENT_V02 != pLocLatencyInfo->latencyInfo) {
        LOC_LOGe("Invalid Latency Info Type");
        return;
    }

    /* check refCount */
    if (pLocLatencyInfo->fCountOfMeasBlk != mRefFCount) {
        LOC_LOGw("FCount mismatch: Latency Fcount=%d Meas. FCount=%d",
                 pLocLatencyInfo->fCountOfMeasBlk,
                 mRefFCount);
        return;
    }

    if (pLocLatencyInfo->sysTickAtChkPt1_valid) {
        gnssLatencyInfo.meQtimer1 = pLocLatencyInfo->sysTickAtChkPt1;
    }
    if (pLocLatencyInfo->sysTickAtChkPt2_valid) {
        gnssLatencyInfo.meQtimer2 = pLocLatencyInfo->sysTickAtChkPt2;
    }
    if (pLocLatencyInfo->sysTickAtChkPt3_valid) {
        gnssLatencyInfo.meQtimer3 = pLocLatencyInfo->sysTickAtChkPt3;
    }
    if (pLocLatencyInfo->sysTickAtChkPt4_valid) {
        gnssLatencyInfo.peQtimer1 = pLocLatencyInfo->sysTickAtChkPt4;
    }
    if (pLocLatencyInfo->sysTickAtChkPt5_valid) {
        gnssLatencyInfo.peQtimer2 = pLocLatencyInfo->sysTickAtChkPt5;
    }
    if (pLocLatencyInfo->sysTickAtChkPt6_valid) {
        gnssLatencyInfo.peQtimer3 = pLocLatencyInfo->sysTickAtChkPt6;
    }
    if (pLocLatencyInfo->sysTickAtChkPt7_valid) {
        gnssLatencyInfo.smQtimer1 = pLocLatencyInfo->sysTickAtChkPt7;
    }
    if (pLocLatencyInfo->sysTickAtChkPt8_valid) {
        gnssLatencyInfo.smQtimer2 = pLocLatencyInfo->sysTickAtChkPt8;
    }
    if (pLocLatencyInfo->sysTickAtChkPt9_valid) {
        gnssLatencyInfo.smQtimer3 = pLocLatencyInfo->sysTickAtChkPt9;
    }
    if (pLocLatencyInfo->sysTickAtChkPt10_valid) {
        gnssLatencyInfo.locMwQtimer = pLocLatencyInfo->sysTickAtChkPt10;
    }
    gnssLatencyInfo.hlosQtimer1 = mHlosQtimer1;
    gnssLatencyInfo.hlosQtimer2 = mHlosQtimer2;
    LOC_LOGv("meQtimer1=%" PRIi64 " "
             "meQtimer2=%" PRIi64 " "
             "meQtimer3=%" PRIi64 " "
             "peQtimer1=%" PRIi64 " "
             "peQtimer2=%" PRIi64 " "
             "peQtimer3=%" PRIi64 " "
             "smQtimer1=%" PRIi64 " "
             "smQtimer2=%" PRIi64 " "
             "smQtimer3=%" PRIi64 " "
             "locMwQtimer=%" PRIi64 " "
             "hlosQtimer1=%" PRIi64 " "
             "hlosQtimer2=%" PRIi64 " ",
             gnssLatencyInfo.meQtimer1, gnssLatencyInfo.meQtimer2,
             gnssLatencyInfo.meQtimer3, gnssLatencyInfo.peQtimer1, gnssLatencyInfo.peQtimer2,
             gnssLatencyInfo.peQtimer3, gnssLatencyInfo.smQtimer1, gnssLatencyInfo.smQtimer2,
             gnssLatencyInfo.smQtimer3, gnssLatencyInfo.locMwQtimer,
             gnssLatencyInfo.hlosQtimer1, gnssLatencyInfo.hlosQtimer2);

    LocApiBase::reportLatencyInfo(gnssLatencyInfo);
}

void LocApiV02::configRobustLocation
        (bool enable, bool enableForE911, LocApiResponse *adapterResponse) {

    sendMsg(new LocApiMsg([this, enable, enableForE911, adapterResponse] () {

    LocationError err = LOCATION_ERROR_SUCCESS;
    qmiLocSetRobustLocationReqMsgT_v02 req;
    qmiLocGenReqStatusIndMsgT_v02 ind;
    locClientStatusEnumType status;
    locClientReqUnionType req_union;

    LOC_LOGd("Enter. enabled %d, enableForE911 %d", enable, enableForE911);
    memset(&req, 0, sizeof(req));
    memset(&ind, 0, sizeof(ind));
    req.enable = enable;
    req.enableForE911_valid = true;
    req.enableForE911 = enableForE911;
    if (enable == false && enableForE911 == true) {
        LOC_LOGw("enableForE911 is not allowed when enable is set to false");
        // change enableForE911 to false to simplify processing
        req.enableForE911 = false;
    }

    req_union.pSetRobustLocationReq = &req;
    status = locSyncSendReq(QMI_LOC_SET_ROBUST_LOCATION_CONFIG_REQ_V02,
                            req_union, LOC_ENGINE_SYNC_REQUEST_LONG_TIMEOUT,
                            QMI_LOC_SET_ROBUST_LOCATION_CONFIG_IND_V02,
                            &ind);
    if (status != eLOC_CLIENT_SUCCESS || ind.status != eQMI_LOC_SUCCESS_V02) {
        LOC_LOGe("failed. status: %s, ind status:%s\n",
                 loc_get_v02_client_status_name(status),
                 loc_get_v02_qmi_status_name(ind.status));
        if (status == eLOC_CLIENT_FAILURE_UNSUPPORTED ||
                status == eLOC_CLIENT_FAILURE_INVALID_MESSAGE_ID) {
            err = LOCATION_ERROR_NOT_SUPPORTED;
        } else {
            err = LOCATION_ERROR_GENERAL_FAILURE;
        }
    }
    if (adapterResponse) {
        adapterResponse->returnToSender(err);
    }
    LOC_LOGv("Exit. err: %u", err);
    }));
}

void LocApiV02 :: getRobustLocationConfig(uint32_t sessionId, LocApiResponse *adapterResponse)
{
    sendMsg(new LocApiMsg([this, sessionId, adapterResponse] () {

    int ret=0;
    LocationError err = LOCATION_ERROR_SUCCESS;
    locClientStatusEnumType status = eLOC_CLIENT_FAILURE_GENERAL;
    locClientReqUnionType req_union = {};
    qmiLocGetRobustLocationConfigIndMsgT_v02 getRobustLocationConfigInd = {};

    status = locSyncSendReq(QMI_LOC_GET_ROBUST_LOCATION_CONFIG_REQ_V02,
                            req_union, LOC_ENGINE_SYNC_REQUEST_LONG_TIMEOUT,
                            QMI_LOC_GET_ROBUST_LOCATION_CONFIG_IND_V02,
                            &getRobustLocationConfigInd);

    if ((status == eLOC_CLIENT_SUCCESS) &&
        (getRobustLocationConfigInd.status == eQMI_LOC_SUCCESS_V02)) {
        err = LOCATION_ERROR_SUCCESS;
    }else {
        LOC_LOGe("getRobustLocationConfig: failed. status: %s, ind status:%s",
                 loc_get_v02_client_status_name(status),
                 loc_get_v02_qmi_status_name(getRobustLocationConfigInd.status));
        if (status == eLOC_CLIENT_FAILURE_UNSUPPORTED ||
                status == eLOC_CLIENT_FAILURE_INVALID_MESSAGE_ID) {
            err = LOCATION_ERROR_NOT_SUPPORTED;
        } else {
            err = LOCATION_ERROR_GENERAL_FAILURE;
        }
    }

    if (LOCATION_ERROR_SUCCESS != err) {
        adapterResponse->returnToSender(err);
    } else {
        GnssConfig config = {};
        uint32_t robustLocationValidMask = 0;
        config.flags |= GNSS_CONFIG_FLAGS_ROBUST_LOCATION_BIT;
        if (getRobustLocationConfigInd.isEnabled_valid) {
            robustLocationValidMask |= GNSS_CONFIG_ROBUST_LOCATION_ENABLED_VALID_BIT;
        }
        if (getRobustLocationConfigInd.isEnabledForE911_valid) {
            robustLocationValidMask |= GNSS_CONFIG_ROBUST_LOCATION_ENABLED_FOR_E911_VALID_BIT;
        }
        if (getRobustLocationConfigInd.robustLocationVersion_valid) {
            robustLocationValidMask |= GNSS_CONFIG_ROBUST_LOCATION_VERSION_VALID_BIT ;
        }

        config.robustLocationConfig.validMask =
                (GnssConfigRobustLocationValidMask) robustLocationValidMask;
        config.robustLocationConfig.enabled = getRobustLocationConfigInd.isEnabled;
        config.robustLocationConfig.enabledForE911 = getRobustLocationConfigInd.isEnabledForE911;
        config.robustLocationConfig.version.major =
                getRobustLocationConfigInd.robustLocationVersion.major;
        config.robustLocationConfig.version.minor =
                getRobustLocationConfigInd.robustLocationVersion.minor;

        LOC_LOGd("session id: %d, mask: 0x%x, enabled: %d, enabledForE911: %d, version: %d %d",
                 sessionId, config.robustLocationConfig.validMask,
                 config.robustLocationConfig.enabled,
                 config.robustLocationConfig.enabledForE911,
                 config.robustLocationConfig.version.major,
                 config.robustLocationConfig.version.minor);

        LocApiBase::reportGnssConfig(sessionId, config);
    }

    LOC_LOGv("Exit. err: %u", err);
    }));
}

void LocApiV02::configMinGpsWeek(uint16_t minGpsWeek, LocApiResponse *adapterResponse) {

    sendMsg(new LocApiMsg([this, minGpsWeek, adapterResponse] () {

    LOC_LOGd("Enter. minGpsWeek %d", minGpsWeek);

    LocationError err = LOCATION_ERROR_SUCCESS;
    qmiLocSetMinGpsWeekNumberReqMsgT_v02 req = {};
    qmiLocGenReqStatusIndMsgT_v02 ind = {};
    locClientStatusEnumType status;
    locClientReqUnionType req_union = {};

    req.minGpsWeekNumber = minGpsWeek;
    req_union.pSetMinGpsWeekReq = &req;

    status = locSyncSendReq(QMI_LOC_SET_MIN_GPS_WEEK_NUMBER_REQ_V02,
                            req_union, LOC_ENGINE_SYNC_REQUEST_LONG_TIMEOUT,
                            QMI_LOC_SET_MIN_GPS_WEEK_NUMBER_IND_V02,
                            &ind);
    if (status != eLOC_CLIENT_SUCCESS || ind.status != eQMI_LOC_SUCCESS_V02) {
        LOC_LOGe("failed. status: %s, ind status:%s",
                 loc_get_v02_client_status_name(status),
                 loc_get_v02_qmi_status_name(ind.status));
        if (status == eLOC_CLIENT_FAILURE_UNSUPPORTED ||
                status == eLOC_CLIENT_FAILURE_INVALID_MESSAGE_ID) {
            err = LOCATION_ERROR_NOT_SUPPORTED;
        } else {
            err = LOCATION_ERROR_GENERAL_FAILURE;
        }
    }
    if (adapterResponse) {
        adapterResponse->returnToSender(err);
    }
    LOC_LOGv("Exit. err: %u", err);
    }));
}

void LocApiV02 :: getMinGpsWeek(uint32_t sessionId, LocApiResponse *adapterResponse)
{
    sendMsg(new LocApiMsg([this, sessionId, adapterResponse] () {

    LocationError err = LOCATION_ERROR_SUCCESS;
    locClientStatusEnumType status = eLOC_CLIENT_FAILURE_GENERAL;
    locClientReqUnionType req_union = {};
    qmiLocGetMinGpsWeekNumberIndMsgT_v02 getInd = {};
    uint16_t minGpsWeek = 0;

    status = locSyncSendReq(QMI_LOC_GET_MIN_GPS_WEEK_NUMBER_REQ_V02,
                            req_union, LOC_ENGINE_SYNC_REQUEST_LONG_TIMEOUT,
                            QMI_LOC_GET_MIN_GPS_WEEK_NUMBER_IND_V02,
                            &getInd);

    if ((status == eLOC_CLIENT_SUCCESS) && (getInd.status == eQMI_LOC_SUCCESS_V02) &&
            getInd.minGpsWeekNumber_valid) {
        minGpsWeek = getInd.minGpsWeekNumber;
        err = LOCATION_ERROR_SUCCESS;
    }else {
        LOC_LOGe("failed. status: %s, ind status:%s",
                 loc_get_v02_client_status_name(status),
                 loc_get_v02_qmi_status_name(getInd.status));
        if (status == eLOC_CLIENT_FAILURE_UNSUPPORTED ||
                status == eLOC_CLIENT_FAILURE_INVALID_MESSAGE_ID) {
            err = LOCATION_ERROR_NOT_SUPPORTED;
        } else {
            err = LOCATION_ERROR_GENERAL_FAILURE;
        }
    }

    if (LOCATION_ERROR_SUCCESS != err) {
        adapterResponse->returnToSender(err);
    } else {
        GnssConfig config = {};
        config.flags |= GNSS_CONFIG_FLAGS_MIN_GPS_WEEK_BIT;
        config.minGpsWeek = minGpsWeek;
        LOC_LOGd("session id %d, minGpsWeek %d", sessionId, minGpsWeek);
        LocApiBase::reportGnssConfig(sessionId, config);
    }

    LOC_LOGe("Exit. err: %u", err);
    }));
}

LocationError LocApiV02::setParameterSync(const GnssConfig & gnssConfig) {
    LocationError err = LOCATION_ERROR_NOT_SUPPORTED;
    qmiLocSetParameterReqMsgT_v02 req = {};
    qmiLocGenReqStatusIndMsgT_v02 ind = {};
    locClientStatusEnumType status = eLOC_CLIENT_FAILURE_GENERAL;
    locClientReqUnionType req_union = {};

    req.paramType = eQMI_LOC_PARAMETER_TYPE_RESERVED_V02;
    if (gnssConfig.flags & GNSS_CONFIG_FLAGS_MIN_SV_ELEVATION_BIT) {
        req.paramType = eQMI_LOC_PARAMETER_TYPE_MINIMUM_SV_ELEVATION_V02;
        req.minSvElevation_valid = 1;
        req.minSvElevation = gnssConfig.minSvElevation;
        LOC_LOGd("set min sv elevation to %d", req.minSvElevation);
    }

    if (req.paramType != eQMI_LOC_PARAMETER_TYPE_RESERVED_V02) {
        req_union.pSetParameterReq = &req;
        status = locSyncSendReq(QMI_LOC_SET_PARAMETER_REQ_V02,
                                req_union, LOC_ENGINE_SYNC_REQUEST_LONG_TIMEOUT,
                                QMI_LOC_SET_PARAMETER_IND_V02,
                                &ind);
        if (status != eLOC_CLIENT_SUCCESS || ind.status != eQMI_LOC_SUCCESS_V02) {
            LOC_LOGe("failed. status: %s, ind status:%s\n",
                     loc_get_v02_client_status_name(status),
                     loc_get_v02_qmi_status_name(ind.status));
            if (status == eLOC_CLIENT_FAILURE_UNSUPPORTED ||
                    status == eLOC_CLIENT_FAILURE_INVALID_MESSAGE_ID) {
                err = LOCATION_ERROR_NOT_SUPPORTED;
            } else {
                err = LOCATION_ERROR_GENERAL_FAILURE;
            }
        } else {
            err = LOCATION_ERROR_SUCCESS;
        }
    }

    LOC_LOGv("Exit. err: %u", err);
    return err;
}

void LocApiV02 :: getParameter(uint32_t sessionId, GnssConfigFlagsMask flags,
                               LocApiResponse* adapterResponse) {

    LOC_LOGe ("get parameter 0x%x", flags);
    sendMsg(new LocApiMsg([this, sessionId, flags, adapterResponse] () {

    LocationError err = LOCATION_ERROR_GENERAL_FAILURE;
    locClientStatusEnumType status = eLOC_CLIENT_FAILURE_GENERAL;
    locClientReqUnionType req_union = {};
    qmiLocGetParameterReqMsgT_v02 getParameterReq = {};
    qmiLocGetParameterIndMsgT_v02 getParameterInd = {};
    GnssConfig config = {};

    do {
        getParameterReq.paramType = eQMI_LOC_PARAMETER_TYPE_RESERVED_V02;
        switch (flags) {
        case GNSS_CONFIG_FLAGS_MIN_SV_ELEVATION_BIT:
            getParameterReq.paramType = eQMI_LOC_PARAMETER_TYPE_MINIMUM_SV_ELEVATION_V02;
            break;
        default:
            break;
        }

        if (getParameterReq.paramType == eQMI_LOC_PARAMETER_TYPE_RESERVED_V02) {
            err = LOCATION_ERROR_NOT_SUPPORTED;
            break;
        }

        req_union.pGetParameterReq = &getParameterReq;
        status = locSyncSendReq(QMI_LOC_GET_PARAMETER_REQ_V02,
                                req_union, LOC_ENGINE_SYNC_REQUEST_LONG_TIMEOUT,
                                QMI_LOC_GET_PARAMETER_IND_V02,
                                &getParameterInd);

        if (!((status == eLOC_CLIENT_SUCCESS) &&
              (getParameterInd.status == eQMI_LOC_SUCCESS_V02))) {
            LOC_LOGe("getParameterConfig: failed. status: %s, ind status:%s",
                     loc_get_v02_client_status_name(status),
                     loc_get_v02_qmi_status_name(getParameterInd.status));
            if (status == eLOC_CLIENT_FAILURE_UNSUPPORTED ||
                    status == eLOC_CLIENT_FAILURE_INVALID_MESSAGE_ID) {
                err = LOCATION_ERROR_NOT_SUPPORTED;
            } else {
                err = LOCATION_ERROR_GENERAL_FAILURE;
            }
            break;
        }

        switch (flags) {
        case GNSS_CONFIG_FLAGS_MIN_SV_ELEVATION_BIT:
            if ((getParameterInd.paramType == eQMI_LOC_PARAMETER_TYPE_MINIMUM_SV_ELEVATION_V02) &&
                    (getParameterInd.minSvElevation_valid == 1)) {
                config.flags = GNSS_CONFIG_FLAGS_MIN_SV_ELEVATION_BIT;
                config.minSvElevation = getParameterInd.minSvElevation;
                err = LOCATION_ERROR_SUCCESS;
            }
            break;
        default:
            break;
        }
    } while (0);

    if (config.flags) {
        LocApiBase::reportGnssConfig(sessionId, config);
    } else {
        // return to the caller on failure
        if (adapterResponse) {
            adapterResponse->returnToSender(err);
        }
    }
    LOC_LOGv("Exit. err: %u", err);

    }));
}

bool LocApiV02 :: cacheGnssMeasurementSupport()
{
    bool gnssMeasurementSupported = false;

    /*for GNSS Measurement service, use
      QMI_LOC_SET_GNSS_CONSTELL_REPORT_CONFIG_V02
      to check if modem support this feature or not*/

    if (LOC_API_ADAPTER_ERR_SUCCESS ==
        setSvMeasurementConstellation(QMI_LOC_EVENT_MASK_GNSS_MEASUREMENT_REPORT_V02)) {
        gnssMeasurementSupported = true;
    }

    LOC_LOGd("gnssMeasurementSupported is %d\n", gnssMeasurementSupported);

    return gnssMeasurementSupported;
}

locClientStatusEnumType LocApiV02::locSyncSendReq(uint32_t req_id,
        locClientReqUnionType req_payload, uint32_t timeout_msec,
        uint32_t ind_id, void* ind_payload_ptr) {
    locClientStatusEnumType status = loc_sync_send_req(clientHandle, req_id, req_payload,
            timeout_msec, ind_id, ind_payload_ptr);
    if (eLOC_CLIENT_FAILURE_ENGINE_BUSY == status ||
            (eLOC_CLIENT_SUCCESS == status && nullptr != ind_payload_ptr &&
            eQMI_LOC_ENGINE_BUSY_V02 == *((qmiLocStatusEnumT_v02*)ind_payload_ptr))) {
        if (mResenders.empty() && ((mQmiMask & QMI_LOC_EVENT_MASK_ENGINE_STATE_V02) == 0)) {
            locClientRegisterEventMask(clientHandle,
                                       mQmiMask | QMI_LOC_EVENT_MASK_ENGINE_STATE_V02, isMaster());
        }
        LOC_LOGd("Engine busy, cache req: %d", req_id);
        uint32_t reqLen = 0;
        void* pReqData = nullptr;
        locClientReqUnionType req_payload_copy = {nullptr};
        validateRequest(req_id, req_payload, &pReqData, &reqLen);
        if (nullptr != pReqData) {
            req_payload_copy.pReqData = malloc(reqLen);
            if (nullptr != req_payload_copy.pReqData) {
                memcpy(req_payload_copy.pReqData, pReqData, reqLen);
            }
        }
        // something would be wrong if (nullptr != pReqData && nullptr == req_payload_copy)
        if (nullptr == pReqData || nullptr != req_payload_copy.pReqData) {
            mResenders.push_back([=](){
                    // ignore indicator, we use nullptr as the last parameter
                    loc_sync_send_req(clientHandle, req_id, req_payload_copy,
                                      timeout_msec, ind_id, nullptr);
                    if (nullptr != req_payload_copy.pReqData) {
                        free(req_payload_copy.pReqData);
                    }
                });
        }
    }
    return status;
}

void LocApiV02 ::
handleWwanZppFixIndication(const qmiLocGetAvailWwanPositionIndMsgT_v02& zpp_ind)
{
    LocGpsLocation zppLoc;
    memset(&zppLoc, 0, sizeof(zppLoc));

    LOC_LOGD("Got Wwan Zpp fix location validity (lat:%d, lon:%d, timestamp:%d accuracy:%d)\n "
             "(%.7f, %.7f), timestamp %" PRIu64 ", accuracy %f",
             zpp_ind.latitude_valid,
             zpp_ind.longitude_valid,
             zpp_ind.timestampUtc_valid,
             zpp_ind.horUncCircular_valid,
             zpp_ind.latitude,
             zpp_ind.longitude,
             zpp_ind.timestampUtc,
             zpp_ind.horUncCircular);

    if ((zpp_ind.latitude_valid == false) ||
        (zpp_ind.longitude_valid == false) ||
        (zpp_ind.horUncCircular_valid == false)) {
        LOC_LOGE(" Location not valid lat=%u lon=%u unc=%u",
                 zpp_ind.latitude_valid,
                 zpp_ind.longitude_valid,
                 zpp_ind.horUncCircular_valid);
    } else {

        zppLoc.size = sizeof(LocGpsLocation);
        if (zpp_ind.timestampUtc_valid) {
            zppLoc.timestamp = zpp_ind.timestampUtc;
        } else {
            /* The UTC time from modem is not valid.
            In this case, we use current system time instead.*/

            struct timespec time_info_current;
            clock_gettime(CLOCK_REALTIME,&time_info_current);
            zppLoc.timestamp = (time_info_current.tv_sec)*1e3 +
                               (time_info_current.tv_nsec)/1e6;
            LOC_LOGD("zpp timestamp got from system: %" PRIu64, zppLoc.timestamp);
        }

        zppLoc.flags = LOC_GPS_LOCATION_HAS_LAT_LONG | LOC_GPS_LOCATION_HAS_ACCURACY;
        zppLoc.latitude = zpp_ind.latitude;
        zppLoc.longitude = zpp_ind.longitude;
        zppLoc.accuracy = zpp_ind.horUncCircular;

        // If horCircularConfidence_valid is true, and horCircularConfidence value
        // is less than 68%, then scale the accuracy value to 68% confidence.
        if (zpp_ind.horCircularConfidence_valid)
        {
            scaleAccuracyTo68PercentConfidence(zpp_ind.horCircularConfidence,
                                               zppLoc, true);
        }

        if (zpp_ind.altitudeWrtEllipsoid_valid) {
            zppLoc.flags |= LOC_GPS_LOCATION_HAS_ALTITUDE;
            zppLoc.altitude = zpp_ind.altitudeWrtEllipsoid;
        }

        if (zpp_ind.vertUnc_valid) {
            zppLoc.flags |= LOC_GPS_LOCATION_HAS_VERT_UNCERTAINITY;
            zppLoc.vertUncertainity = zpp_ind.vertUnc;
        }
    }

    LocApiBase::reportWwanZppFix(zppLoc);
}

void LocApiV02::
    handleZppBestAvailableFixIndication(const qmiLocGetBestAvailablePositionIndMsgT_v02 &zpp_ind)
{
    LocGpsLocation zppLoc;
    GpsLocationExtended location_extended;
    LocPosTechMask tech_mask;

    memset(&zppLoc, 0, sizeof(zppLoc));
    zppLoc.size = sizeof(zppLoc);

    memset(&location_extended, 0, sizeof(location_extended));
    location_extended.size = sizeof(location_extended);

    tech_mask = LOC_POS_TECH_MASK_DEFAULT;

    LOC_LOGD("Got Zpp fix location validity (lat:%d, lon:%d, timestamp:%d accuracy:%d)"
            " (%.7f, %.7f), timestamp %" PRIu64 ", accuracy %f",
            zpp_ind.latitude_valid,
            zpp_ind.longitude_valid,
            zpp_ind.timestampUtc_valid,
            zpp_ind.horUncCircular_valid,
            zpp_ind.latitude,
            zpp_ind.longitude,
            zpp_ind.timestampUtc,
            zpp_ind.horUncCircular);

        if (zpp_ind.timestampUtc_valid) {
            zppLoc.timestamp = zpp_ind.timestampUtc;
        } else {
            /* The UTC time from modem is not valid.
                    In this case, we use current system time instead.*/

          struct timespec time_info_current;
          clock_gettime(CLOCK_REALTIME,&time_info_current);
          zppLoc.timestamp = (time_info_current.tv_sec)*1e3 +
                  (time_info_current.tv_nsec)/1e6;
          LOC_LOGD("zpp timestamp got from system: %" PRIu64, zppLoc.timestamp);
        }

        if (zpp_ind.latitude_valid && zpp_ind.longitude_valid &&
                zpp_ind.horUncCircular_valid ) {
            zppLoc.flags = LOC_GPS_LOCATION_HAS_LAT_LONG | LOC_GPS_LOCATION_HAS_ACCURACY;
            zppLoc.latitude = zpp_ind.latitude;
            zppLoc.longitude = zpp_ind.longitude;
            zppLoc.accuracy = zpp_ind.horUncCircular;

            // If horCircularConfidence_valid is true, and horCircularConfidence value
            // is less than 68%, then scale the accuracy value to 68% confidence.
            if (zpp_ind.horCircularConfidence_valid)
            {
                scaleAccuracyTo68PercentConfidence(zpp_ind.horCircularConfidence,
                                                   zppLoc, true);
            }

            if (zpp_ind.altitudeWrtEllipsoid_valid) {
                zppLoc.flags |= LOC_GPS_LOCATION_HAS_ALTITUDE;
                zppLoc.altitude = zpp_ind.altitudeWrtEllipsoid;
            }

            if (zpp_ind.horSpeed_valid) {
                zppLoc.flags |= LOC_GPS_LOCATION_HAS_SPEED;
                zppLoc.speed = zpp_ind.horSpeed;
            }

            if (zpp_ind.heading_valid) {
                zppLoc.flags |= LOC_GPS_LOCATION_HAS_BEARING;
                zppLoc.bearing = zpp_ind.heading;
            }

            if (zpp_ind.vertUnc_valid) {
                location_extended.flags |= GPS_LOCATION_EXTENDED_HAS_VERT_UNC;
                location_extended.vert_unc = zpp_ind.vertUnc;
            }

            if (zpp_ind.horSpeedUnc_valid) {
                location_extended.flags |= GPS_LOCATION_EXTENDED_HAS_SPEED_UNC;
                location_extended.speed_unc = zpp_ind.horSpeedUnc;
            }

            if (zpp_ind.headingUnc_valid) {
                location_extended.flags |= GPS_LOCATION_EXTENDED_HAS_BEARING_UNC;
                location_extended.bearing_unc = zpp_ind.headingUnc;
            }

            if (zpp_ind.technologyMask_valid) {
                tech_mask = zpp_ind.technologyMask;
            }

            if(zpp_ind.spoofReportMask_valid) {
                zppLoc.flags |= LOC_GPS_LOCATION_HAS_SPOOF_MASK;
                zppLoc.spoof_mask = (uint32_t)zpp_ind.spoofReportMask;
                LOC_LOGD("%s:%d QMI_spoofReportMask:0x%x", __func__, __LINE__,
                             (uint8_t)zppLoc.spoof_mask);
            }
        }

        LocApiBase::reportZppBestAvailableFix(zppLoc, location_extended, tech_mask);
}


LocPosTechMask LocApiV02 :: convertPosTechMask(
  qmiLocPosTechMaskT_v02 mask)
{
   LocPosTechMask locTechMask = LOC_POS_TECH_MASK_DEFAULT;

   if (mask & QMI_LOC_POS_TECH_MASK_SATELLITE_V02)
      locTechMask |= LOC_POS_TECH_MASK_SATELLITE;

   if (mask & QMI_LOC_POS_TECH_MASK_CELLID_V02)
      locTechMask |= LOC_POS_TECH_MASK_CELLID;

   if (mask & QMI_LOC_POS_TECH_MASK_WIFI_V02)
      locTechMask |= LOC_POS_TECH_MASK_WIFI;

   if (mask & QMI_LOC_POS_TECH_MASK_SENSORS_V02)
      locTechMask |= LOC_POS_TECH_MASK_SENSORS;

   if (mask & QMI_LOC_POS_TECH_MASK_REFERENCE_LOCATION_V02)
      locTechMask |= LOC_POS_TECH_MASK_REFERENCE_LOCATION;

   if (mask & QMI_LOC_POS_TECH_MASK_INJECTED_COARSE_POSITION_V02)
      locTechMask |= LOC_POS_TECH_MASK_INJECTED_COARSE_POSITION;

   if (mask & QMI_LOC_POS_TECH_MASK_AFLT_V02)
      locTechMask |= LOC_POS_TECH_MASK_AFLT;

   if (mask & QMI_LOC_POS_TECH_MASK_HYBRID_V02)
      locTechMask |= LOC_POS_TECH_MASK_HYBRID;

   return locTechMask;
}

LocNavSolutionMask LocApiV02 :: convertNavSolutionMask(
  qmiLocNavSolutionMaskT_v02 mask)
{
   LocNavSolutionMask locNavMask = 0;

   if (mask & QMI_LOC_NAV_MASK_SBAS_CORRECTION_IONO_V02)
      locNavMask |= LOC_NAV_MASK_SBAS_CORRECTION_IONO;

   if (mask & QMI_LOC_NAV_MASK_SBAS_CORRECTION_FAST_V02)
      locNavMask |= LOC_NAV_MASK_SBAS_CORRECTION_FAST;

   if (mask & QMI_LOC_POS_TECH_MASK_WIFI_V02)
      locNavMask |= LOC_POS_TECH_MASK_WIFI;

   if (mask & QMI_LOC_NAV_MASK_SBAS_CORRECTION_LONG_V02)
      locNavMask |= LOC_NAV_MASK_SBAS_CORRECTION_LONG;

   if (mask & QMI_LOC_NAV_MASK_SBAS_INTEGRITY_V02)
      locNavMask |= LOC_NAV_MASK_SBAS_INTEGRITY;

   if (mask & QMI_LOC_NAV_MASK_CORRECTION_DGNSS_V02)
      locNavMask |= LOC_NAV_MASK_DGNSS_CORRECTION;

   if (mask & QMI_LOC_NAV_MASK_ONLY_SBAS_CORRECTED_SV_USED_V02)
      locNavMask |= LOC_NAV_MASK_ONLY_SBAS_CORRECTED_SV_USED;

   return locNavMask;
}

qmiLocApnTypeMaskT_v02 LocApiV02::convertLocApnTypeMask(LocApnTypeMask mask)
{
    qmiLocApnTypeMaskT_v02 qmiMask = 0;

    if (mask & LOC_APN_TYPE_MASK_DEFAULT) {
        qmiMask |= QMI_LOC_APN_TYPE_MASK_DEFAULT_V02;
    }
    if (mask & LOC_APN_TYPE_MASK_IMS) {
        qmiMask |= QMI_LOC_APN_TYPE_MASK_IMS_V02;
    }
    if (mask & LOC_APN_TYPE_MASK_MMS) {
        qmiMask |= QMI_LOC_APN_TYPE_MASK_MMS_V02;
    }
    if (mask & LOC_APN_TYPE_MASK_DUN) {
        qmiMask |= QMI_LOC_APN_TYPE_MASK_DUN_V02;
    }
    if (mask & LOC_APN_TYPE_MASK_SUPL) {
        qmiMask |= QMI_LOC_APN_TYPE_MASK_SUPL_V02;
    }
    if (mask & LOC_APN_TYPE_MASK_HIPRI) {
        qmiMask |= QMI_LOC_APN_TYPE_MASK_HIPRI_V02;
    }
    if (mask & LOC_APN_TYPE_MASK_FOTA) {
        qmiMask |= QMI_LOC_APN_TYPE_MASK_FOTA_V02;
    }
    if (mask & LOC_APN_TYPE_MASK_CBS) {
        qmiMask |= QMI_LOC_APN_TYPE_MASK_CBS_V02;
    }
    if (mask & LOC_APN_TYPE_MASK_IA) {
        qmiMask |= QMI_LOC_APN_TYPE_MASK_IA_V02;
    }
    if (mask & LOC_APN_TYPE_MASK_EMERGENCY) {
        qmiMask |= QMI_LOC_APN_TYPE_MASK_EMERGENCY_V02;
    }

    return qmiMask;
}

LocApnTypeMask LocApiV02::convertQmiLocApnTypeMask(qmiLocApnTypeMaskT_v02 qmiMask)
{
    LocApnTypeMask mask = 0;

    if (qmiMask & QMI_LOC_APN_TYPE_MASK_DEFAULT_V02) {
        mask |= LOC_APN_TYPE_MASK_DEFAULT;
    }
    if (qmiMask & QMI_LOC_APN_TYPE_MASK_IMS_V02) {
        mask |= LOC_APN_TYPE_MASK_IMS;
    }
    if (qmiMask & QMI_LOC_APN_TYPE_MASK_MMS_V02) {
        mask |= LOC_APN_TYPE_MASK_MMS;
    }
    if (qmiMask & QMI_LOC_APN_TYPE_MASK_DUN_V02) {
        mask |= LOC_APN_TYPE_MASK_DUN;
    }
    if (qmiMask & QMI_LOC_APN_TYPE_MASK_SUPL_V02) {
        mask |= LOC_APN_TYPE_MASK_SUPL;
    }
    if (qmiMask & QMI_LOC_APN_TYPE_MASK_HIPRI_V02) {
        mask |= LOC_APN_TYPE_MASK_HIPRI;
    }
    if (qmiMask & QMI_LOC_APN_TYPE_MASK_FOTA_V02) {
        mask |= LOC_APN_TYPE_MASK_FOTA;
    }
    if (qmiMask & QMI_LOC_APN_TYPE_MASK_CBS_V02) {
        mask |= LOC_APN_TYPE_MASK_CBS;
    }
    if (qmiMask & QMI_LOC_APN_TYPE_MASK_IA_V02) {
        mask |= LOC_APN_TYPE_MASK_IA;
    }
    if (qmiMask & QMI_LOC_APN_TYPE_MASK_EMERGENCY_V02) {
        mask |= LOC_APN_TYPE_MASK_EMERGENCY;
    }

    return mask;
}

GnssConfigSuplVersion
LocApiV02::convertSuplVersion(const uint32_t suplVersion)
{
    switch (suplVersion) {
        case 0x00020004:
            return GNSS_CONFIG_SUPL_VERSION_2_0_4;
        case 0x00020002:
            return GNSS_CONFIG_SUPL_VERSION_2_0_2;
        case 0x00020000:
            return GNSS_CONFIG_SUPL_VERSION_2_0_0;
        case 0x00010000:
        default:
            return GNSS_CONFIG_SUPL_VERSION_1_0_0;
    }
}

GnssConfigLppeControlPlaneMask
LocApiV02::convertLppeCp(const uint32_t lppeControlPlaneMask)
{
    GnssConfigLppeControlPlaneMask mask = 0;
    if ((1<<0) & lppeControlPlaneMask) {
        mask |= GNSS_CONFIG_LPPE_CONTROL_PLANE_DBH_BIT;
    }
    if ((1<<1) & lppeControlPlaneMask) {
        mask |= GNSS_CONFIG_LPPE_CONTROL_PLANE_WLAN_AP_MEASUREMENTS_BIT;
    }
    if ((1<<2) & lppeControlPlaneMask) {
        mask |= GNSS_CONFIG_LPPE_CONTROL_PLANE_SRN_AP_MEASUREMENTS_BIT;
    }
    if ((1<<3) & lppeControlPlaneMask) {
        mask |= GNSS_CONFIG_LPPE_CONTROL_PLANE_SENSOR_BARO_MEASUREMENTS_BIT;
    }
    return mask;
}

GnssConfigLppeUserPlaneMask
LocApiV02::convertLppeUp(const uint32_t lppeUserPlaneMask)
{
    GnssConfigLppeUserPlaneMask mask = 0;
    if ((1 << 0) & lppeUserPlaneMask) {
        mask |= GNSS_CONFIG_LPPE_USER_PLANE_DBH_BIT;
    }
    if ((1 << 1) & lppeUserPlaneMask) {
        mask |= GNSS_CONFIG_LPPE_USER_PLANE_WLAN_AP_MEASUREMENTS_BIT;
    }
    if ((1 << 2) & lppeUserPlaneMask) {
        mask |= GNSS_CONFIG_LPPE_USER_PLANE_SRN_AP_MEASUREMENTS_BIT;
    }
    if ((1 << 3) & lppeUserPlaneMask) {
        mask |= GNSS_CONFIG_LPPE_USER_PLANE_SENSOR_BARO_MEASUREMENTS_BIT;
    }
    return mask;
}

LocationError
LocApiV02::setEmergencyExtensionWindowSync(const uint32_t emergencyExtensionSeconds)
{
    LocationError err = LOCATION_ERROR_SUCCESS;
    locClientStatusEnumType result = eLOC_CLIENT_SUCCESS;
    locClientReqUnionType req_union;
    qmiLocSetProtocolConfigParametersReqMsgT_v02 eCbW_req;
    qmiLocSetProtocolConfigParametersIndMsgT_v02 eCbW_ind;

    memset(&eCbW_req, 0, sizeof(eCbW_req));
    memset(&eCbW_ind, 0, sizeof(eCbW_ind));

    eCbW_req.emergencyCallbackWindow_valid = 1;
    eCbW_req.emergencyCallbackWindow = emergencyExtensionSeconds;

    req_union.pSetProtocolConfigParametersReq = &eCbW_req;

    LOC_LOGd("emergencyCallbackWindow = %d", emergencyExtensionSeconds);

    result = locSyncSendReq(QMI_LOC_SET_PROTOCOL_CONFIG_PARAMETERS_REQ_V02,
        req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT,
        QMI_LOC_SET_PROTOCOL_CONFIG_PARAMETERS_IND_V02,
        &eCbW_ind);

    if (result != eLOC_CLIENT_SUCCESS ||
        eQMI_LOC_SUCCESS_V02 != eCbW_ind.status)
    {
        LOC_LOGe("Error status = %s, ind..status = %s ",
            loc_get_v02_client_status_name(result),
            loc_get_v02_qmi_status_name(eCbW_ind.status));
        err = LOCATION_ERROR_GENERAL_FAILURE;
    }

    return err;
}

void
LocApiV02::setMeasurementCorrections(const GnssMeasurementCorrections& gnssMeasurementCorrections)
{
    sendMsg(new LocApiMsg([this, gnssMeasurementCorrections] {

    LocationError err = LOCATION_ERROR_SUCCESS;
    locClientStatusEnumType result = eLOC_CLIENT_SUCCESS;
    locClientReqUnionType req_union = {};

    qmiLocEventInjectEnvAidingReqMsgT_v02 setEnvAidingReqMsg;
    qmiLocGenReqStatusIndMsgT_v02 genReqStatusIndMsg;

    memset(&setEnvAidingReqMsg, 0, sizeof(setEnvAidingReqMsg));
    memset(&genReqStatusIndMsg, 0, sizeof(genReqStatusIndMsg));

    LOC_LOGv("GnssMeasurementCorrections from modem:\n"
             " hasEnvironmentBearing = %d"
             " environmentBearingDegrees = %.2f"
             " environmentBearingUncertaintyDegrees = %.2f"
             " latitudeDegrees = %.2f"
             " longitudeDegrees = %.2f"
             " horizontalPositionUncertaintyMeters = %.2f"
             " altitudeMeters = %.2f"
             " verticalPositionUncertaintyMeters = %.2f"
             " toaGpsNanosecondsOfWeek = %" PRIu64,
             gnssMeasurementCorrections.hasEnvironmentBearing,
             gnssMeasurementCorrections.environmentBearingDegrees,
             gnssMeasurementCorrections.environmentBearingUncertaintyDegrees,
             gnssMeasurementCorrections.latitudeDegrees,
             gnssMeasurementCorrections.longitudeDegrees,
             gnssMeasurementCorrections.horizontalPositionUncertaintyMeters,
             gnssMeasurementCorrections.altitudeMeters,
             gnssMeasurementCorrections.verticalPositionUncertaintyMeters,
             gnssMeasurementCorrections.toaGpsNanosecondsOfWeek);

    for (int i = 0; i < gnssMeasurementCorrections.satCorrections.size(); i++) {
        LOC_LOGv("gnssMeasurementCorrections.satCorrections:\n"
            "satCorrections[%d].svType = %d "
            "satCorrections[%d].svId = %d "
            "satCorrections[%d].carrierFrequencyHz = %.2f "
            "satCorrections[%d].probSatIsLos = %.2f "
            "satCorrections[%d].excessPathLengthMeters = %.2f "
            "satCorrections[%d].excessPathLengthUncertaintyMeters = %.2f "
            "satCorrections[%d].reflectingPlane.latitudeDegree = %.2f "
            "satCorrections[%d].reflectingPlane.longitudeDegrees = %.2f "
            "satCorrections[%d].reflectingPlane.altitudeMeters = %.2f "
            "satCorrections[%d].reflectingPlane.azimuthDegrees = %.2f ",
            i, gnssMeasurementCorrections.satCorrections[i].svType,
            i, gnssMeasurementCorrections.satCorrections[i].svId,
            i, gnssMeasurementCorrections.satCorrections[i].carrierFrequencyHz,
            i, gnssMeasurementCorrections.satCorrections[i].probSatIsLos,
            i, gnssMeasurementCorrections.satCorrections[i].excessPathLengthMeters,
            i, gnssMeasurementCorrections.satCorrections[i].excessPathLengthUncertaintyMeters,
            i, gnssMeasurementCorrections.satCorrections[i].reflectingPlane.latitudeDegrees,
            i, gnssMeasurementCorrections.satCorrections[i].reflectingPlane.longitudeDegrees,
            i, gnssMeasurementCorrections.satCorrections[i].reflectingPlane.altitudeMeters,
            i, gnssMeasurementCorrections.satCorrections[i].reflectingPlane.azimuthDegrees);
    }

    setEnvAidingReqMsg.maxMessageNum = 1;
    setEnvAidingReqMsg.seqNum = 1;

    setEnvAidingReqMsg.envBearingValidity_valid = true;
    setEnvAidingReqMsg.envBearingValidity = gnssMeasurementCorrections.hasEnvironmentBearing;
    setEnvAidingReqMsg.envBearingDegrees_valid = true;
    setEnvAidingReqMsg.envBearingDegrees = gnssMeasurementCorrections.environmentBearingDegrees;
    setEnvAidingReqMsg.envBearingUncDegrees_valid = true;
    setEnvAidingReqMsg.envBearingUncDegrees =
            gnssMeasurementCorrections.environmentBearingUncertaintyDegrees;

    setEnvAidingReqMsg.latitudeDegrees_valid = true;
    setEnvAidingReqMsg.latitudeDegrees = gnssMeasurementCorrections.latitudeDegrees;
    setEnvAidingReqMsg.longitudeDegrees_valid = true;
    setEnvAidingReqMsg.longitudeDegrees = gnssMeasurementCorrections.longitudeDegrees;
    setEnvAidingReqMsg.horizontalPositionUncMeters_valid = true;
    setEnvAidingReqMsg.horizontalPositionUncMeters =
            gnssMeasurementCorrections.horizontalPositionUncertaintyMeters;
    setEnvAidingReqMsg.altitudeMeters_valid = true;
    setEnvAidingReqMsg.altitudeMeters = gnssMeasurementCorrections.altitudeMeters;
    setEnvAidingReqMsg.altitudeUncMeters_valid = true;
    setEnvAidingReqMsg.altitudeUncMeters =
            gnssMeasurementCorrections.verticalPositionUncertaintyMeters;
    setEnvAidingReqMsg.toaGpsNanosecondsOfWeek_valid = true;
    setEnvAidingReqMsg.toaGpsNanosecondsOfWeek =
            gnssMeasurementCorrections.toaGpsNanosecondsOfWeek;

    uint32_t len = gnssMeasurementCorrections.satCorrections.size();
    if (len > 0) {
        if (len >= QMI_LOC_ENV_AIDING_CORRECTION_MAX_SV_USED_V02) {
            setEnvAidingReqMsg.svCorrection_len = QMI_LOC_ENV_AIDING_CORRECTION_MAX_SV_USED_V02;
        } else {
            setEnvAidingReqMsg.svCorrection_len = len;
        }
        setEnvAidingReqMsg.svCorrection_valid = true;
        for (int i = 0; i < setEnvAidingReqMsg.svCorrection_len; i++) {
            setEnvAidingReqMsg.svCorrection[i].svCorrectionFlags = 0;
            if (gnssMeasurementCorrections.satCorrections[i].flags &
                (GNSS_MEAS_CORR_HAS_SAT_IS_LOS_PROBABILITY_BIT)) {
                setEnvAidingReqMsg.svCorrection[i].probabilitySvIsLineofSight =
                        gnssMeasurementCorrections.satCorrections[i].probSatIsLos;
                setEnvAidingReqMsg.svCorrection[i].svCorrectionFlags |=
                        QMI_LOC_ENV_AIDING_SV_CORRECTION_LINE_OF_SIGHT_PROBABILITY_VALID_V02;
            }
            if (gnssMeasurementCorrections.satCorrections[i].flags &
                (GNSS_MEAS_CORR_HAS_EXCESS_PATH_LENGTH_BIT)) {
                setEnvAidingReqMsg.svCorrection[i].excessPathLengthMeters =
                        gnssMeasurementCorrections.satCorrections[i].excessPathLengthMeters;
                setEnvAidingReqMsg.svCorrection[i].svCorrectionFlags |=
                        QMI_LOC_ENV_AIDING_SV_CORRECTION_EXCESS_PATH_LENGTH_VALID_V02;
            }
            if (gnssMeasurementCorrections.satCorrections[i].flags &
                (GNSS_MEAS_CORR_HAS_EXCESS_PATH_LENGTH_UNC_BIT)) {
                setEnvAidingReqMsg.svCorrection[i].excessPathLengthUncMeters =
                        gnssMeasurementCorrections.satCorrections[i].
                                excessPathLengthUncertaintyMeters;
                setEnvAidingReqMsg.svCorrection[i].svCorrectionFlags |=
                        QMI_LOC_ENV_AIDING_SV_CORRECTION_EXCESS_PATH_LENGTH_UNC_VALID_V02;
            }
            if (gnssMeasurementCorrections.satCorrections[i].flags &
                (GNSS_MEAS_CORR_HAS_REFLECTING_PLANE_BIT)) {
                setEnvAidingReqMsg.svCorrection[i].reflectingPlane.latitudeDegrees =
                        gnssMeasurementCorrections.satCorrections[i].
                                reflectingPlane.latitudeDegrees;
                setEnvAidingReqMsg.svCorrection[i].reflectingPlane.longitudeDegrees =
                        gnssMeasurementCorrections.satCorrections[i].
                                reflectingPlane.longitudeDegrees;
                setEnvAidingReqMsg.svCorrection[i].reflectingPlane.altitudeMeters =
                        gnssMeasurementCorrections.satCorrections[i].
                                reflectingPlane.altitudeMeters;
                setEnvAidingReqMsg.svCorrection[i].reflectingPlane.azimuthDegrees =
                        gnssMeasurementCorrections.satCorrections[i].
                                reflectingPlane.azimuthDegrees;
                setEnvAidingReqMsg.svCorrection[i].svCorrectionFlags |=
                        QMI_LOC_ENV_AIDING_SV_CORRECTION_REFLECTING_PLANE_VALID_V02;
            }
            switch (gnssMeasurementCorrections.satCorrections[i].svType) {
            case GNSS_SV_TYPE_GPS:
                setEnvAidingReqMsg.svCorrection[i].constellation =
                        eQMI_LOC_SV_SYSTEM_GPS_V02;
                break;

            case GNSS_SV_TYPE_SBAS:
                setEnvAidingReqMsg.svCorrection[i].constellation =
                        eQMI_LOC_SV_SYSTEM_SBAS_V02;
                break;

            case GNSS_SV_TYPE_GLONASS:
                setEnvAidingReqMsg.svCorrection[i].constellation =
                        eQMI_LOC_SV_SYSTEM_GLONASS_V02;
                break;

            case GNSS_SV_TYPE_QZSS:
                setEnvAidingReqMsg.svCorrection[i].constellation =
                        eQMI_LOC_SV_SYSTEM_QZSS_V02;
                break;

            case GNSS_SV_TYPE_BEIDOU:
                setEnvAidingReqMsg.svCorrection[i].constellation =
                        eQMI_LOC_SV_SYSTEM_BDS_V02;
                break;

            case GNSS_SV_TYPE_GALILEO:
                setEnvAidingReqMsg.svCorrection[i].constellation =
                        eQMI_LOC_SV_SYSTEM_GALILEO_V02;
                break;

            case GNSS_SV_TYPE_NAVIC:
                setEnvAidingReqMsg.svCorrection[i].constellation =
                        eQMI_LOC_SV_SYSTEM_NAVIC_V02;
                break;

            case GNSS_SV_TYPE_UNKNOWN:
            default:
                break;
            }
            setEnvAidingReqMsg.svCorrection[i].svid =
                    gnssMeasurementCorrections.satCorrections[i].svId;
            setEnvAidingReqMsg.svCorrection[i].carrierFrequencyHz =
                    gnssMeasurementCorrections.satCorrections[i].carrierFrequencyHz;
        }
    }

    req_union.pEnvAidingReqMsg = &setEnvAidingReqMsg;

    result = locSyncSendReq(QMI_LOC_INJECT_ENV_AIDING_REQ_V02,
                            req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT,
                            QMI_LOC_INJECT_ENV_AIDING_IND_V02,
                            &genReqStatusIndMsg);

    if (result != eLOC_CLIENT_SUCCESS ||
        eQMI_LOC_SUCCESS_V02 != genReqStatusIndMsg.status)
    {
        LOC_LOGe("Error status = %s, ind..status = %s ",
            loc_get_v02_client_status_name(result),
            loc_get_v02_qmi_status_name(genReqStatusIndMsg.status));
        err = LOCATION_ERROR_GENERAL_FAILURE;
    }

    }));
}

LocationError
LocApiV02::setBlacklistSvSync(const GnssSvIdConfig& config)
{
    locClientStatusEnumType status = eLOC_CLIENT_FAILURE_GENERAL;
    locClientReqUnionType req_union = {};

    qmiLocSetBlacklistSvReqMsgT_v02 setBlacklistSvMsg;
    qmiLocGenReqStatusIndMsgT_v02 genReqStatusIndMsg;

    // Clear all fields
    memset(&setBlacklistSvMsg, 0, sizeof(setBlacklistSvMsg));
    memset(&genReqStatusIndMsg, 0, sizeof(genReqStatusIndMsg));

    // Fill in the request details
    setBlacklistSvMsg.glo_persist_blacklist_sv_valid = true;
    setBlacklistSvMsg.glo_persist_blacklist_sv = config.gloBlacklistSvMask;
    setBlacklistSvMsg.glo_clear_persist_blacklist_sv_valid = true;
    setBlacklistSvMsg.glo_clear_persist_blacklist_sv = ~config.gloBlacklistSvMask;

    setBlacklistSvMsg.bds_persist_blacklist_sv_valid = true;
    setBlacklistSvMsg.bds_persist_blacklist_sv = config.bdsBlacklistSvMask;
    setBlacklistSvMsg.bds_clear_persist_blacklist_sv_valid = true;
    setBlacklistSvMsg.bds_clear_persist_blacklist_sv = ~config.bdsBlacklistSvMask;

    setBlacklistSvMsg.qzss_persist_blacklist_sv_valid = true;
    setBlacklistSvMsg.qzss_persist_blacklist_sv = config.qzssBlacklistSvMask;
    setBlacklistSvMsg.qzss_clear_persist_blacklist_sv_valid = true;
    setBlacklistSvMsg.qzss_clear_persist_blacklist_sv = ~config.qzssBlacklistSvMask;

    setBlacklistSvMsg.gal_persist_blacklist_sv_valid = true;
    setBlacklistSvMsg.gal_persist_blacklist_sv = config.galBlacklistSvMask;
    setBlacklistSvMsg.gal_clear_persist_blacklist_sv_valid = true;
    setBlacklistSvMsg.gal_clear_persist_blacklist_sv = ~config.galBlacklistSvMask;

    setBlacklistSvMsg.sbas_persist_blacklist_sv_valid = true;
    setBlacklistSvMsg.sbas_persist_blacklist_sv = config.sbasBlacklistSvMask,
    setBlacklistSvMsg.sbas_clear_persist_blacklist_sv_valid = true;
    setBlacklistSvMsg.sbas_clear_persist_blacklist_sv = ~config.sbasBlacklistSvMask;

    setBlacklistSvMsg.navic_persist_blacklist_sv_valid = true;
    setBlacklistSvMsg.navic_persist_blacklist_sv = config.navicBlacklistSvMask,
    setBlacklistSvMsg.navic_clear_persist_blacklist_sv_valid = true;
    setBlacklistSvMsg.navic_clear_persist_blacklist_sv = ~config.navicBlacklistSvMask;

    LOC_LOGd(">>> configConstellations, "
             "glo blacklist mask =0x%" PRIx64 ", "
             "qzss blacklist mask =0x%" PRIx64 ",\n"
             "bds blacklist mask =0x%" PRIx64 ", "
             "gal blacklist mask =0x%" PRIx64 ",\n"
             "sbas blacklist mask =0x%" PRIx64 ", "
             "navic blacklist mask =0x%" PRIx64 ", ",
             setBlacklistSvMsg.glo_persist_blacklist_sv,
             setBlacklistSvMsg.qzss_persist_blacklist_sv,
             setBlacklistSvMsg.bds_persist_blacklist_sv,
             setBlacklistSvMsg.gal_persist_blacklist_sv,
             setBlacklistSvMsg.sbas_persist_blacklist_sv,
             setBlacklistSvMsg.navic_persist_blacklist_sv);
    // Update in request union
    req_union.pSetBlacklistSvReq = &setBlacklistSvMsg;

    // Send the request
    status = loc_sync_send_req(clientHandle,
                               QMI_LOC_SET_BLACKLIST_SV_REQ_V02,
                               req_union,
                               LOC_ENGINE_SYNC_REQUEST_TIMEOUT,
                               QMI_LOC_SET_BLACKLIST_SV_IND_V02,
                               &genReqStatusIndMsg);
    if(status != eLOC_CLIENT_SUCCESS ||
            genReqStatusIndMsg.status != eQMI_LOC_SUCCESS_V02) {
        LOC_LOGe("Set Blacklist SV failed. status: %s ind status %s",
                 loc_get_v02_client_status_name(status),
                 loc_get_v02_qmi_status_name(genReqStatusIndMsg.status));
        return LOCATION_ERROR_GENERAL_FAILURE;
    }

    return LOCATION_ERROR_SUCCESS;
}

void
LocApiV02::setBlacklistSv(const GnssSvIdConfig& config, LocApiResponse* adapterResponse)
{
    sendMsg(new LocApiMsg([this, config, adapterResponse] () {
                LocationError err = setBlacklistSvSync(config);
                if (adapterResponse) {
                    adapterResponse->returnToSender(err);
                }
            }));
}

void LocApiV02::getBlacklistSv()
{
    sendMsg(new LocApiMsg([this] () {

    locClientStatusEnumType status = eLOC_CLIENT_FAILURE_GENERAL;
    locClientReqUnionType req_union = {};

    // Nothing to update in request union

    // Send the request
    status = locClientSendReq(QMI_LOC_GET_BLACKLIST_SV_REQ_V02, req_union);
    if(status != eLOC_CLIENT_SUCCESS) {
        LOC_LOGe("Get Blacklist SV failed. status: %s",
                 loc_get_v02_client_status_name(status));
    }

    }));
}

void
LocApiV02::setConstellationControl(const GnssSvTypeConfig& config,
                                   LocApiResponse *adapterResponse)
{
    // QMI will return INVALID parameter if enabledSvTypesMask is 0,
    // so we just return back to the caller as this is no-op
    if (0 == config.enabledSvTypesMask) {
        if (NULL != adapterResponse) {
            adapterResponse->returnToSender(LOCATION_ERROR_SUCCESS);
        }
        return;
    }

    sendMsg(new LocApiMsg([this, config, adapterResponse] () {

    locClientStatusEnumType status = eLOC_CLIENT_FAILURE_GENERAL;
    locClientReqUnionType req_union = {};

    qmiLocSetConstellationConfigReqMsgT_v02 setConstellationConfigMsg;
    qmiLocGenReqStatusIndMsgT_v02 genReqStatusIndMsg;

    // Clear all fields
    memset (&setConstellationConfigMsg, 0, sizeof(setConstellationConfigMsg));
    memset(&genReqStatusIndMsg, 0, sizeof(genReqStatusIndMsg));

    // Fill in the request details
    setConstellationConfigMsg.resetConstellations = false;

    setConstellationConfigMsg.enableMask_valid = true;
    setConstellationConfigMsg.enableMask = config.enabledSvTypesMask;

    // disableMask is not supported in modem
    // if we set disableMask, QMI call will return error
    LOC_LOGe("enable: %d 0x%" PRIx64 ", blacklisted: %d 0x%" PRIx64 "",
             setConstellationConfigMsg.enableMask_valid,
             setConstellationConfigMsg.enableMask,
             setConstellationConfigMsg.disableMask_valid,
             setConstellationConfigMsg.disableMask);

    // Update in request union
    req_union.pSetConstellationConfigReq = &setConstellationConfigMsg;

    // Send the request
    status = loc_sync_send_req(clientHandle,
                               QMI_LOC_SET_CONSTELLATION_CONTROL_REQ_V02,
                               req_union,
                               LOC_ENGINE_SYNC_REQUEST_TIMEOUT,
                               QMI_LOC_SET_CONSTELLATION_CONTROL_IND_V02,
                               &genReqStatusIndMsg);
    if(status != eLOC_CLIENT_SUCCESS ||
            genReqStatusIndMsg.status != eQMI_LOC_SUCCESS_V02) {
        LOC_LOGe("Set Constellation Config failed. status: %s ind status %s",
                 loc_get_v02_client_status_name(status),
                 loc_get_v02_qmi_status_name(genReqStatusIndMsg.status));
    }

    LocationError err = LOCATION_ERROR_GENERAL_FAILURE;
    if (eLOC_CLIENT_SUCCESS == status) {
        err = LOCATION_ERROR_SUCCESS;
    }

    if (adapterResponse != NULL) {
        adapterResponse->returnToSender(err);
    }

    }));
}

void
LocApiV02::getConstellationControl()
{
    sendMsg(new LocApiMsg([this] () {

    locClientStatusEnumType status = eLOC_CLIENT_FAILURE_GENERAL;
    locClientReqUnionType req_union = {};

    qmiLocGetConstellationConfigIndMsgT_v02 getConstIndMsg;
    memset(&getConstIndMsg, 0, sizeof(getConstIndMsg));

    // Nothing to update in request union

    // Send the request
    status = loc_sync_send_req(clientHandle,
                               QMI_LOC_GET_CONSTELLATION_CONTROL_REQ_V02,
                               req_union,
                               LOC_ENGINE_SYNC_REQUEST_TIMEOUT,
                               QMI_LOC_GET_CONSTELLATION_CONTROL_IND_V02,
                               &getConstIndMsg);
    if(status == eLOC_CLIENT_SUCCESS &&
            getConstIndMsg.status == eQMI_LOC_SUCCESS_V02) {
        LOC_LOGd("GET constellation Ind");
        reportGnssSvTypeConfig(getConstIndMsg);
    } else {
        LOC_LOGe("Get Constellation failed. status: %s, ind status: %s",
                 loc_get_v02_client_status_name(status),
                 loc_get_v02_qmi_status_name(getConstIndMsg.status));
    }

    }));
}

void
LocApiV02::resetConstellationControl(LocApiResponse *adapterResponse)
{
    sendMsg(new LocApiMsg([this, adapterResponse] () {

    locClientStatusEnumType status = eLOC_CLIENT_FAILURE_GENERAL;
    locClientReqUnionType req_union = {};

    qmiLocSetConstellationConfigReqMsgT_v02 setConstellationConfigMsg;
    qmiLocGenReqStatusIndMsgT_v02 genReqStatusIndMsg;

    // Clear all fields
    memset (&setConstellationConfigMsg, 0, sizeof(setConstellationConfigMsg));
    memset(&genReqStatusIndMsg, 0, sizeof(genReqStatusIndMsg));

    // Fill in the request details
    setConstellationConfigMsg.resetConstellations = true;

    // Update in request union
    req_union.pSetConstellationConfigReq = &setConstellationConfigMsg;

    // Send the request
    status = loc_sync_send_req(clientHandle,
                               QMI_LOC_SET_CONSTELLATION_CONTROL_REQ_V02,
                               req_union,
                               LOC_ENGINE_SYNC_REQUEST_TIMEOUT,
                               QMI_LOC_SET_CONSTELLATION_CONTROL_IND_V02,
                               &genReqStatusIndMsg);
    if(status != eLOC_CLIENT_SUCCESS ||
            genReqStatusIndMsg.status != eQMI_LOC_SUCCESS_V02) {
        LOC_LOGe("Reset Constellation Config failed. "
                 "status: %s ind status %s",
                 loc_get_v02_client_status_name(status),
                 loc_get_v02_qmi_status_name(genReqStatusIndMsg.status));
    }

    LocationError err = LOCATION_ERROR_GENERAL_FAILURE;
    if (eLOC_CLIENT_SUCCESS == status) {
        err = LOCATION_ERROR_SUCCESS;
    }
    if (adapterResponse) {
        adapterResponse->returnToSender(err);
    }
    }));
}

void
LocApiV02::reportGnssSvIdConfig(
        const qmiLocGetBlacklistSvIndMsgT_v02& ind)
{
    // Validate status
    if (ind.status != eQMI_LOC_SUCCESS_V02) {
        LOC_LOGe("Ind failure status %d", ind.status);
        return;
    }

    // Parse all fields
    GnssSvIdConfig config = {};
    convertQmiBlacklistedSvConfigToGnssConfig(ind, config);
    // Pass on GnssSvConfig
    LocApiBase::reportGnssSvIdConfig(config);
}

void
LocApiV02::reportGnssSvTypeConfig(
        const qmiLocGetConstellationConfigIndMsgT_v02& ind)
{
    // Validate status
    if (ind.status != eQMI_LOC_SUCCESS_V02) {
        LOC_LOGe("Ind failure status %d", ind.status);
        return;
    }

    // Parse all fields
    GnssSvTypeConfig config = {};
    config.size = sizeof(GnssSvTypeConfig);
    convertToGnssSvTypeConfig(ind, config);

    // Pass on GnssSvConfig
    LocApiBase::reportGnssSvTypeConfig(config);
}

void
LocApiV02::convertToGnssSvTypeConfig(
        const qmiLocGetConstellationConfigIndMsgT_v02& ind,
        GnssSvTypeConfig& config)
{
    // Enabled Mask
    if (ind.bds_status_valid &&
            (ind.bds_status == eQMI_LOC_CONSTELLATION_ENABLED_MANDATORY_V02 ||
                    ind.bds_status == eQMI_LOC_CONSTELLATION_ENABLED_INTERNALLY_V02 ||
                    ind.bds_status == eQMI_LOC_CONSTELLATION_ENABLED_BY_CLIENT_V02)) {
        config.enabledSvTypesMask |= GNSS_SV_TYPES_MASK_BDS_BIT;
    }
    if (ind.glonass_status_valid &&
            (ind.glonass_status == eQMI_LOC_CONSTELLATION_ENABLED_MANDATORY_V02 ||
                    ind.glonass_status == eQMI_LOC_CONSTELLATION_ENABLED_INTERNALLY_V02 ||
                    ind.glonass_status == eQMI_LOC_CONSTELLATION_ENABLED_BY_CLIENT_V02)) {
        config.enabledSvTypesMask |= GNSS_SV_TYPES_MASK_GLO_BIT;
    }
    if (ind.galileo_status_valid &&
            (ind.galileo_status == eQMI_LOC_CONSTELLATION_ENABLED_MANDATORY_V02 ||
                    ind.galileo_status == eQMI_LOC_CONSTELLATION_ENABLED_INTERNALLY_V02 ||
                    ind.galileo_status == eQMI_LOC_CONSTELLATION_ENABLED_BY_CLIENT_V02)) {
        config.enabledSvTypesMask |= GNSS_SV_TYPES_MASK_GAL_BIT;
    }
    if (ind.qzss_status_valid &&
            (ind.qzss_status == eQMI_LOC_CONSTELLATION_ENABLED_MANDATORY_V02 ||
                    ind.qzss_status == eQMI_LOC_CONSTELLATION_ENABLED_INTERNALLY_V02 ||
                    ind.qzss_status == eQMI_LOC_CONSTELLATION_ENABLED_BY_CLIENT_V02)) {
        config.enabledSvTypesMask |= GNSS_SV_TYPES_MASK_QZSS_BIT;
    }
    if (ind.navic_status_valid &&
            (ind.navic_status == eQMI_LOC_CONSTELLATION_ENABLED_MANDATORY_V02 ||
                    ind.navic_status == eQMI_LOC_CONSTELLATION_ENABLED_INTERNALLY_V02 ||
                    ind.navic_status == eQMI_LOC_CONSTELLATION_ENABLED_BY_CLIENT_V02)) {
        config.enabledSvTypesMask |= GNSS_SV_TYPES_MASK_NAVIC_BIT;
    }

    // Disabled Mask
    if (ind.bds_status_valid &&
            (ind.bds_status == eQMI_LOC_CONSTELLATION_DISABLED_NOT_SUPPORTED_V02 ||
                    ind.bds_status == eQMI_LOC_CONSTELLATION_DISABLED_INTERNALLY_V02 ||
                    ind.bds_status == eQMI_LOC_CONSTELLATION_DISABLED_BY_CLIENT_V02 ||
                    ind.bds_status == eQMI_LOC_CONSTELLATION_DISABLED_NO_MEMORY_V02)) {
        config.blacklistedSvTypesMask |= GNSS_SV_TYPES_MASK_BDS_BIT;
    }
    if (ind.glonass_status_valid &&
            (ind.glonass_status == eQMI_LOC_CONSTELLATION_DISABLED_NOT_SUPPORTED_V02 ||
                    ind.glonass_status == eQMI_LOC_CONSTELLATION_DISABLED_INTERNALLY_V02 ||
                    ind.glonass_status == eQMI_LOC_CONSTELLATION_DISABLED_BY_CLIENT_V02 ||
                    ind.glonass_status == eQMI_LOC_CONSTELLATION_DISABLED_NO_MEMORY_V02)) {
        config.blacklistedSvTypesMask |= GNSS_SV_TYPES_MASK_GLO_BIT;
    }
    if (ind.galileo_status_valid &&
            (ind.galileo_status == eQMI_LOC_CONSTELLATION_DISABLED_NOT_SUPPORTED_V02 ||
                    ind.galileo_status == eQMI_LOC_CONSTELLATION_DISABLED_INTERNALLY_V02 ||
                    ind.galileo_status == eQMI_LOC_CONSTELLATION_DISABLED_BY_CLIENT_V02 ||
                    ind.galileo_status == eQMI_LOC_CONSTELLATION_DISABLED_NO_MEMORY_V02)) {
        config.blacklistedSvTypesMask |= GNSS_SV_TYPES_MASK_GAL_BIT;
    }
    if (ind.qzss_status_valid &&
            (ind.qzss_status == eQMI_LOC_CONSTELLATION_DISABLED_NOT_SUPPORTED_V02 ||
                    ind.qzss_status == eQMI_LOC_CONSTELLATION_DISABLED_INTERNALLY_V02 ||
                    ind.qzss_status == eQMI_LOC_CONSTELLATION_DISABLED_BY_CLIENT_V02 ||
                    ind.qzss_status == eQMI_LOC_CONSTELLATION_DISABLED_NO_MEMORY_V02)) {
        config.blacklistedSvTypesMask |= GNSS_SV_TYPES_MASK_QZSS_BIT;
    }
    if (ind.navic_status_valid &&
            (ind.navic_status == eQMI_LOC_CONSTELLATION_DISABLED_NOT_SUPPORTED_V02 ||
                    ind.navic_status == eQMI_LOC_CONSTELLATION_DISABLED_INTERNALLY_V02 ||
                    ind.navic_status == eQMI_LOC_CONSTELLATION_DISABLED_BY_CLIENT_V02 ||
                    ind.navic_status == eQMI_LOC_CONSTELLATION_DISABLED_NO_MEMORY_V02)) {
        config.blacklistedSvTypesMask |= GNSS_SV_TYPES_MASK_NAVIC_BIT;
    }
}

void LocApiV02::onDbtPosReportEvent(const qmiLocEventDbtPositionReportIndMsgT_v02* pDbtPosReport)
{
    UlpLocation location;
    memset (&location, 0, sizeof (location));
    location.size = sizeof(location);
    const qmiLocDbtPositionStructT_v02 *pReport = &pDbtPosReport->dbtPosition;

    // time stamp
    location.gpsLocation.timestamp = pReport->timestampUtc;
    // latitude & longitude
    location.gpsLocation.flags |= LOC_GPS_LOCATION_HAS_LAT_LONG;
    location.gpsLocation.latitude  = pReport->latitude;
    location.gpsLocation.longitude = pReport->longitude;
    // Altitude
    if (pReport->altitudeWrtEllipsoid_valid == 1) {
        location.gpsLocation.flags |= LOC_GPS_LOCATION_HAS_ALTITUDE;
        location.gpsLocation.altitude = pReport->altitudeWrtEllipsoid;
    }
    // Speed
    if (pReport->speedHorizontal_valid == 1) {
        location.gpsLocation.flags |= LOC_GPS_LOCATION_HAS_SPEED;
        location.gpsLocation.speed = pReport->speedHorizontal;
    }
    // Heading
    if (pReport->heading_valid == 1) {
        location.gpsLocation.flags |= LOC_GPS_LOCATION_HAS_BEARING;
        location.gpsLocation.bearing = pReport->heading;
    }
    // Accuracy
    location.gpsLocation.flags |= LOC_GPS_LOCATION_HAS_ACCURACY;
    location.gpsLocation.accuracy = sqrt(pReport->horUncEllipseSemiMinor*
                                         pReport->horUncEllipseSemiMinor +
                                         pReport->horUncEllipseSemiMajor*
                                         pReport->horUncEllipseSemiMajor);
    // Source used
    LocPosTechMask loc_technology_mask = LOC_POS_TECH_MASK_DEFAULT;
    if (pDbtPosReport->positionSrc_valid) {
        switch (pDbtPosReport->positionSrc) {
            case eQMI_LOC_POSITION_SRC_GNSS_V02:
                loc_technology_mask = LOC_POS_TECH_MASK_SATELLITE;
                break;
            case eQMI_LOC_POSITION_SRC_CELLID_V02:
                loc_technology_mask = LOC_POS_TECH_MASK_CELLID;
                break;
            case eQMI_LOC_POSITION_SRC_ENH_CELLID_V02:
                loc_technology_mask = LOC_POS_TECH_MASK_CELLID;
                break;
            case eQMI_LOC_POSITION_SRC_WIFI_V02:
                loc_technology_mask = LOC_POS_TECH_MASK_WIFI;
                break;
            case eQMI_LOC_POSITION_SRC_TERRESTRIAL_V02:
                loc_technology_mask = LOC_POS_TECH_MASK_REFERENCE_LOCATION;
                break;
            case eQMI_LOC_POSITION_SRC_GNSS_TERRESTRIAL_HYBRID_V02:
                loc_technology_mask = LOC_POS_TECH_MASK_HYBRID;
                break;
            default:
                loc_technology_mask = LOC_POS_TECH_MASK_DEFAULT;
        }
    }

    GpsLocationExtended locationExtended;
    memset(&locationExtended, 0, sizeof (GpsLocationExtended));
    locationExtended.size = sizeof(locationExtended);

    if (pReport->vertUnc_valid) {
       locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_VERT_UNC;
       locationExtended.vert_unc = pReport->vertUnc;
    }
    if (pDbtPosReport->speedUnc_valid) {
        locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_SPEED_UNC;
        locationExtended.speed_unc = pDbtPosReport->speedUnc;
    }
    if (pDbtPosReport->headingUnc_valid) {
       locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_BEARING_UNC;
       locationExtended.bearing_unc = pDbtPosReport->headingUnc;
    }
    // Calling the base
    reportDBTPosition(location,
                      locationExtended,
                      LOC_SESS_SUCCESS,
                      loc_technology_mask);
}

void LocApiV02::batchFullEvent(const qmiLocEventBatchFullIndMsgT_v02* batchFullInfo)
{
    struct MsgGetBatchedLocations : public LocMsg {
        LocApiBase& mApi;
        size_t mCount;
        uint32_t mAccumulatedDistance;
        qmiLocBatchingTypeEnumT_v02 mBatchType;
        inline MsgGetBatchedLocations(LocApiV02& api,
                                      size_t count,
                                      uint32_t accumulatedDistance,
                                      qmiLocBatchingTypeEnumT_v02 batchType) :
            LocMsg(),
            mApi(api),
            mCount(count),
            mAccumulatedDistance(accumulatedDistance),
            mBatchType(batchType) {}
        inline virtual void proc() const {
            // Explicit check for if OTB is supported or not to work around an
            // issue with older modems where uninitialized batchInd is being sent
            if ((mBatchType == eQMI_LOC_OUTDOOR_TRIP_BATCHING_V02) &&
                (ContextBase::isMessageSupported(LOC_API_ADAPTER_MESSAGE_OUTDOOR_TRIP_BATCHING))) {
                mApi.getBatchedTripLocationsSync(mCount, mAccumulatedDistance);
            } else {
                mApi.getBatchedLocationsSync(mCount);
            }
        }
    };

    sendMsg(new MsgGetBatchedLocations(*this,
                                        batchFullInfo->batchCount,
                                        (batchFullInfo->accumulatedDistance_valid ?
                                                batchFullInfo->accumulatedDistance: 0),
                                        (batchFullInfo->batchType_valid ? batchFullInfo->batchType :
                                                eQMI_LOC_LOCATION_BATCHING_V02)));

}

void LocApiV02::batchStatusEvent(const qmiLocEventBatchingStatusIndMsgT_v02* batchStatusInfo)
{
    BatchingStatus batchStatus;

    switch(batchStatusInfo->batchingStatus)
    {
        case eQMI_LOC_BATCH_POS_UNAVAILABLE_V02:
            batchStatus = BATCHING_STATUS_POSITION_UNAVAILABLE;
            break;
        case eQMI_LOC_BATCH_POS_AVAILABLE_V02:
            batchStatus = BATCHING_STATUS_POSITION_AVAILABE;
            break;
        default:
            batchStatus = BATCHING_STATUS_POSITION_UNAVAILABLE;
    }

    handleBatchStatusEvent(batchStatus);
}

// For Geofence
void LocApiV02::geofenceBreachEvent(const qmiLocEventGeofenceBreachIndMsgT_v02* breachInfo)
{
    uint32_t hwId = breachInfo->geofenceId;
    int64_t timestamp = time(NULL); // get the current time
    Location location;
    memset(&location, 0, sizeof(Location));
    location.size = sizeof(Location);

    if (breachInfo->geofencePosition_valid) {
        // Latitude & Longitude
        location.flags |= LOCATION_HAS_LAT_LONG_BIT;
        if (breachInfo->geofencePosition.latitude >= -90 &&
            breachInfo->geofencePosition.latitude <= 90 &&
            breachInfo->geofencePosition.longitude >= -180 &&
            breachInfo->geofencePosition.longitude <= 180) {
            // latitude and longitude look to be in the expected format
            location.latitude  = breachInfo->geofencePosition.latitude;
            location.longitude = breachInfo->geofencePosition.longitude;
        }
        else {
            // latitude and longitude must be in wrong format, so convert
            location.latitude  = breachInfo->geofencePosition.latitude * LAT_LONG_TO_RADIANS;
            location.longitude = breachInfo->geofencePosition.longitude * LAT_LONG_TO_RADIANS;
        }

        // Time stamp (UTC)
        location.timestamp = breachInfo->geofencePosition.timestampUtc;

        // Altitude
        location.flags |= LOCATION_HAS_ALTITUDE_BIT;
        location.altitude = breachInfo->geofencePosition.altitudeWrtEllipsoid;

        // Speed
        if (breachInfo->geofencePosition.speedHorizontal_valid == 1) {
            location.flags |= LOCATION_HAS_SPEED_BIT;
            location.speed = breachInfo->geofencePosition.speedHorizontal;
        }

        // Heading
        if (breachInfo->geofencePosition.heading_valid == 1) {
            location.flags |= LOCATION_HAS_BEARING_BIT;
            location.bearing = breachInfo->geofencePosition.heading;
        }

        // Uncertainty (circular)
        location.flags |= LOCATION_HAS_ACCURACY_BIT;
        location.accuracy = sqrt(
            (breachInfo->geofencePosition.horUncEllipseSemiMinor *
            breachInfo->geofencePosition.horUncEllipseSemiMinor) +
            (breachInfo->geofencePosition.horUncEllipseSemiMajor *
            breachInfo->geofencePosition.horUncEllipseSemiMajor));

        location.techMask = LOCATION_TECHNOLOGY_GNSS_BIT;

        LOC_LOGV("%s:%d]: Location lat=%8.2f long=%8.2f ",
                 __func__, __LINE__, location.latitude, location.longitude);

    } else {
       LOC_LOGE("%s:%d]: NO Location ", __func__, __LINE__);
    }

    GeofenceBreachType breachType;
    switch (breachInfo->breachType) {
    case eQMI_LOC_GEOFENCE_BREACH_TYPE_ENTERING_V02:
        breachType = GEOFENCE_BREACH_ENTER;
        break;
    case eQMI_LOC_GEOFENCE_BREACH_TYPE_LEAVING_V02:
        breachType = GEOFENCE_BREACH_EXIT;
        break;
    default:
        breachType = GEOFENCE_BREACH_UNKNOWN;
        break;
    }

    // calling the base
    geofenceBreach(1, &hwId, location, breachType, timestamp);
}

void
LocApiV02::geofenceBreachEvent(const qmiLocEventGeofenceBatchedBreachIndMsgT_v02* breachInfo)
{
    if (NULL == breachInfo)
        return;

    int64_t timestamp = time(NULL); // get the current time
    Location location;
    memset(&location, 0, sizeof(Location));
    location.size = sizeof(Location);

    if (breachInfo->geofencePosition_valid) {
        // Latitude & Longitude
        location.flags |= LOCATION_HAS_LAT_LONG_BIT;
        if (breachInfo->geofencePosition.latitude >= -90 &&
            breachInfo->geofencePosition.latitude <= 90 &&
            breachInfo->geofencePosition.longitude >= -180 &&
            breachInfo->geofencePosition.longitude <= 180) {
            // latitude and longitude look to be in the expected format
            location.latitude  = breachInfo->geofencePosition.latitude;
            location.longitude = breachInfo->geofencePosition.longitude;
        }
        else {
            // latitdue and longitude must be in wrong format, so convert
            location.latitude  = breachInfo->geofencePosition.latitude *
                                 LAT_LONG_TO_RADIANS;
            location.longitude = breachInfo->geofencePosition.longitude *
                                 LAT_LONG_TO_RADIANS;
        }

        // Time stamp (UTC)
        location.timestamp = breachInfo->geofencePosition.timestampUtc;

        // Altitude
        location.flags |= LOCATION_HAS_ALTITUDE_BIT;
        location.altitude = breachInfo->geofencePosition.altitudeWrtEllipsoid;

        // Speed
        if (breachInfo->geofencePosition.speedHorizontal_valid == 1) {
            location.flags |= LOCATION_HAS_SPEED_BIT;
            location.speed = breachInfo->geofencePosition.speedHorizontal;
        }

        // Heading
        if (breachInfo->geofencePosition.heading_valid == 1) {
            location.flags |= LOCATION_HAS_BEARING_BIT;
            location.bearing = breachInfo->geofencePosition.heading;
        }

        // Uncertainty (circular)
        location.flags |= LOCATION_HAS_ACCURACY_BIT;
        location.accuracy = sqrt(
            (breachInfo->geofencePosition.horUncEllipseSemiMinor *
            breachInfo->geofencePosition.horUncEllipseSemiMinor) +
            (breachInfo->geofencePosition.horUncEllipseSemiMajor *
            breachInfo->geofencePosition.horUncEllipseSemiMajor));

        location.techMask = LOCATION_TECHNOLOGY_GNSS_BIT;

        LOC_LOGV("%s]: latitude=%8.2f longitude=%8.2f ",
                 __func__, location.latitude, location.longitude);

    } else {
       LOC_LOGE("%s:%d]: NO Location ", __func__, __LINE__);
    }

    GeofenceBreachType breachType;
    switch (breachInfo->breachType) {
    case eQMI_LOC_GEOFENCE_BREACH_TYPE_ENTERING_V02:
        breachType = GEOFENCE_BREACH_ENTER;
        break;
    case eQMI_LOC_GEOFENCE_BREACH_TYPE_LEAVING_V02:
        breachType = GEOFENCE_BREACH_EXIT;
        break;
    default:
        breachType = GEOFENCE_BREACH_UNKNOWN;
        break;
    }

    size_t count = 0;
    if (1 == breachInfo->geofenceIdDiscreteList_valid) {
        count += breachInfo->geofenceIdDiscreteList_len;
    }

    if (1 == breachInfo->geofenceIdContinuousList_valid) {
        for (uint32_t i = 0; i < breachInfo->geofenceIdContinuousList_len; i++) {
            count += breachInfo->geofenceIdContinuousList[i].idHigh -
                     breachInfo->geofenceIdContinuousList[i].idLow + 1;
        }
    }

    if (0 == count) {
        return;
    }

    uint32_t* hwIds = new uint32_t[count];
    if (hwIds == nullptr) {
        LOC_LOGE("new allocation failed, fatal error.");
        return;
    }
    uint32_t index = 0;
    if (1 == breachInfo->geofenceIdDiscreteList_valid) {
        for (uint32_t i = 0; i<breachInfo->geofenceIdDiscreteList_len; i++) {
            LOC_LOGV("%s]: discrete hwID %u breachType %u",
                     __func__, breachInfo->geofenceIdDiscreteList[i], breachType);
             if (index < count) {
                 hwIds[index++] = breachInfo->geofenceIdDiscreteList[i];
             }
        }
    }

    if (1 == breachInfo->geofenceIdContinuousList_valid) {
        for (uint32_t i = 0; i < breachInfo->geofenceIdContinuousList_len; i++) {
            for (uint32_t j = breachInfo->geofenceIdContinuousList[i].idLow;
                 j <= breachInfo->geofenceIdContinuousList[i].idHigh;
                 j++) {
                     LOC_LOGV("%s]: continuous hwID %u breachType %u",__func__, j, breachType);
                if (index < count) {
                    hwIds[index++] = j;
                }
            }
        }
    }

    // calling the base
    geofenceBreach(count, hwIds, location, breachType, timestamp);

    delete[] hwIds;
}

void LocApiV02::geofenceStatusEvent(const qmiLocEventGeofenceGenAlertIndMsgT_v02* alertInfo)
{
    const char* names[] = {
        "bad value",
        "GEOFENCE_GEN_ALERT_GNSS_UNAVAILABLE",
        "GEOFENCE_GEN_ALERT_GNSS_AVAILABLE",
        "GEOFENCE_GEN_ALERT_OOS",
        "GEOFENCE_GEN_ALERT_TIME_INVALID"
    };
    int index = alertInfo->geofenceAlert;
    if (index < 0 || index > 4) {
        index = 0;
    }
    LOC_LOGV("%s]: GEOFENCE_GEN_ALERT - %s", __func__, names[index]);

    GeofenceStatusAvailable available = GEOFENCE_STATUS_AVAILABILE_NO;
    switch (alertInfo->geofenceAlert) {
    case eQMI_LOC_GEOFENCE_GEN_ALERT_GNSS_UNAVAILABLE_V02:
        available = GEOFENCE_STATUS_AVAILABILE_NO;
        break;
    case eQMI_LOC_GEOFENCE_GEN_ALERT_GNSS_AVAILABLE_V02:
        available = GEOFENCE_STATUS_AVAILABILE_YES;
        break;
    default:
        return;
        break;
    }

    // calling the base
    geofenceStatus(available);
}

void
LocApiV02::geofenceDwellEvent(const qmiLocEventGeofenceBatchedDwellIndMsgT_v02 *dwellInfo)
{
    if (NULL == dwellInfo)
        return;

    int64_t timestamp = time(NULL); // get the current time
    GeofenceBreachType breachType;
    if (eQMI_LOC_GEOFENCE_DWELL_TYPE_INSIDE_V02 == dwellInfo->dwellType) {
        breachType = GEOFENCE_BREACH_DWELL_IN;
    } else if (eQMI_LOC_GEOFENCE_DWELL_TYPE_OUTSIDE_V02 == dwellInfo->dwellType) {
        breachType = GEOFENCE_BREACH_DWELL_OUT;
    } else {
        LOC_LOGW("%s]: unknown dwell type %d", __func__, dwellInfo->dwellType);
        breachType = GEOFENCE_BREACH_UNKNOWN;
    }

    Location location;
    memset(&location, 0, sizeof(Location));
    location.size = sizeof(Location);

    if (dwellInfo->geofencePosition_valid) {
        // Latitude & Longitude
        location.flags |= LOCATION_HAS_LAT_LONG_BIT;
        if (dwellInfo->geofencePosition.latitude >= -90 &&
            dwellInfo->geofencePosition.latitude <= 90 &&
            dwellInfo->geofencePosition.longitude >= -180 &&
            dwellInfo->geofencePosition.longitude <= 180) {
            // latitude and longitude look to be in the expected format
            location.latitude  = dwellInfo->geofencePosition.latitude;
            location.longitude = dwellInfo->geofencePosition.longitude;
        } else {
            // latitude and longitude must be in wrong format, so convert
            location.latitude = dwellInfo->geofencePosition.latitude *
                                   LAT_LONG_TO_RADIANS;
            location.longitude = dwellInfo->geofencePosition.longitude *
                                    LAT_LONG_TO_RADIANS;
        }

        // Time stamp (UTC)
        location.timestamp = dwellInfo->geofencePosition.timestampUtc;

        // Altitude
        location.flags |= LOCATION_HAS_ALTITUDE_BIT;
        location.altitude = dwellInfo->geofencePosition.altitudeWrtEllipsoid;

        // Speed
        if (dwellInfo->geofencePosition.speedHorizontal_valid == 1) {
            location.flags |= LOCATION_HAS_SPEED_BIT;
            location.speed = dwellInfo->geofencePosition.speedHorizontal;
        }

        // Heading
        if (dwellInfo->geofencePosition.heading_valid == 1) {
            location.flags |= LOCATION_HAS_BEARING_BIT;
            location.bearing = dwellInfo->geofencePosition.heading;
        }

        // Uncertainty (circular)
        location.flags |= LOCATION_HAS_ACCURACY_BIT;
        location.accuracy = sqrt(
            (dwellInfo->geofencePosition.horUncEllipseSemiMinor *
            dwellInfo->geofencePosition.horUncEllipseSemiMinor) +
            (dwellInfo->geofencePosition.horUncEllipseSemiMajor *
            dwellInfo->geofencePosition.horUncEllipseSemiMajor));

            LOC_LOGV("%s]: latitude=%8.2f longitude=%8.2f ",
                     __func__, location.latitude, location.longitude);
    } else {
       LOC_LOGE("%s:%d]: NO Location ", __func__, __LINE__);
    }

    size_t count = 0;
    if (1 == dwellInfo->geofenceIdDiscreteList_valid) {
        count += dwellInfo->geofenceIdDiscreteList_len;
    }

    if (1 == dwellInfo->geofenceIdContinuousList_valid) {
        for (uint32_t i = 0; i < dwellInfo->geofenceIdContinuousList_len; i++) {
            count += dwellInfo->geofenceIdContinuousList[i].idHigh -
                     dwellInfo->geofenceIdContinuousList[i].idLow + 1;
        }
    }

    if (0 == count) {
        return;
    }

    uint32_t* hwIds = new uint32_t[count];
    if (hwIds == nullptr) {
        LOC_LOGE("new allocation failed, fatal error.");
        return;
    }
    uint32_t index = 0;
    if (1 == dwellInfo->geofenceIdDiscreteList_valid) {
        for (uint32_t i = 0; i<dwellInfo->geofenceIdDiscreteList_len; i++) {
            LOC_LOGV("%s]: discrete hwID %u breachType %u",
                     __func__, dwellInfo->geofenceIdDiscreteList[i], breachType);
             if (index < count) {
                 hwIds[index++] = dwellInfo->geofenceIdDiscreteList[i];
             }
        }
    }

    if (1 == dwellInfo->geofenceIdContinuousList_valid) {
        for (uint32_t i = 0; i < dwellInfo->geofenceIdContinuousList_len; i++) {
            for (uint32_t j = dwellInfo->geofenceIdContinuousList[i].idLow;
                 j <= dwellInfo->geofenceIdContinuousList[i].idHigh;
                 j++) {
                LOC_LOGV("%s]: continuous hwID %u breachType %u", __func__, j , breachType);
                if (index < count) {
                    hwIds[index++] = j;
                }
            }
        }
    }

    // calling the base
    geofenceBreach(count, hwIds, location, breachType, timestamp);

    delete[] hwIds;
}

void
LocApiV02::addGeofence(uint32_t clientId,
                        const GeofenceOption& options,
                        const GeofenceInfo& info,
                        LocApiResponseData<LocApiGeofenceData>* adapterResponseData)
{
    sendMsg(new LocApiMsg([this, clientId, options, info, adapterResponseData] () {

    LOC_LOGD("%s]: lat=%8.2f long=%8.2f radius %8.2f breach=%u respon=%u dwell=%u",
             __func__, info.latitude, info.longitude, info.radius,
             options.breachTypeMask, options.responsiveness, options.dwellTime);
    LocationError err = LOCATION_ERROR_GENERAL_FAILURE;

    qmiLocAddCircularGeofenceReqMsgT_v02 addReq;
    memset(&addReq, 0, sizeof(addReq));

    if (options.breachTypeMask & GEOFENCE_BREACH_ENTER_BIT)
        addReq.breachMask |= QMI_LOC_GEOFENCE_BREACH_ENTERING_MASK_V02;
    if (options.breachTypeMask & GEOFENCE_BREACH_EXIT_BIT)
        addReq.breachMask |= QMI_LOC_GEOFENCE_BREACH_LEAVING_MASK_V02;

    // confidence
    addReq.confidence_valid = true;
    addReq.confidence = eQMI_LOC_GEOFENCE_CONFIDENCE_HIGH_V02; // always high

    // custom responsiveness
    addReq.customResponsivenessValue_valid = true;
    // The (min,max) custom responsiveness we support in seconds is (1, 65535)
    addReq.customResponsivenessValue =
            ((options.responsiveness < 1000U) ? 1 :
            std::min((options.responsiveness / 1000U), (uint32_t)UINT16_MAX));

    // dwell time
    if (options.dwellTime > 0) {
        addReq.dwellTime_valid = 1;
        addReq.dwellTime = options.dwellTime;
        addReq.dwellTypeMask_valid = 1;
        if (options.breachTypeMask & GEOFENCE_BREACH_DWELL_IN_BIT) {
            addReq.dwellTypeMask |= QMI_LOC_GEOFENCE_DWELL_TYPE_INSIDE_MASK_V02;
        }
        if (options.breachTypeMask & GEOFENCE_BREACH_DWELL_OUT_BIT) {
            addReq.dwellTypeMask |= QMI_LOC_GEOFENCE_DWELL_TYPE_OUTSIDE_MASK_V02;
        }
    }
    addReq.circularGeofenceArgs.latitude = info.latitude;
    addReq.circularGeofenceArgs.longitude = info.longitude;
    addReq.circularGeofenceArgs.radius = info.radius;
    addReq.includePosition = true;
    addReq.transactionId = clientId;

    LOC_SEND_SYNC_REQ(AddCircularGeofence, ADD_CIRCULAR_GEOFENCE, addReq);

    LocApiGeofenceData data;
    if (rv && ind.geofenceId_valid != 0) {
        data.hwId = ind.geofenceId;
        err = LOCATION_ERROR_SUCCESS;
    } else {
        if (eQMI_LOC_MAX_GEOFENCE_PROGRAMMED_V02 == ind.status) {
            err = LOCATION_ERROR_GEOFENCES_AT_MAX;
        }
        LOC_LOGE("%s]: failed! rv is %d, ind.geofenceId_valid is %d",
                 __func__, rv, ind.geofenceId_valid);
    }

    if (adapterResponseData != NULL) {
        adapterResponseData->returnToSender(err, data);
    }
    }));
}

void
LocApiV02::removeGeofence(uint32_t hwId, uint32_t clientId, LocApiResponse* adapterResponse)
{
    sendMsg(new LocApiMsg([this, hwId, clientId, adapterResponse] () {

    LOC_LOGD("%s]: hwId %u", __func__, hwId);
    LocationError err = LOCATION_ERROR_GENERAL_FAILURE;

    qmiLocDeleteGeofenceReqMsgT_v02 deleteReq;
    memset(&deleteReq, 0, sizeof(deleteReq));

    deleteReq.geofenceId = hwId;
    deleteReq.transactionId = clientId;

    LOC_SEND_SYNC_REQ(DeleteGeofence, DELETE_GEOFENCE, deleteReq);

    if (rv) {
        err = LOCATION_ERROR_SUCCESS;
    } else {
        LOC_LOGE("%s]: failed! rv is %d", __func__, rv);
    }

    if (adapterResponse != NULL) {
        adapterResponse->returnToSender(err);
    }
    }));
}

void
LocApiV02::pauseGeofence(uint32_t hwId, uint32_t clientId, LocApiResponse* adapterResponse)
{
    sendMsg(new LocApiMsg([this, hwId, clientId, adapterResponse] () {

    LOC_LOGD("%s]: hwId %u", __func__, hwId);
    LocationError err = LOCATION_ERROR_GENERAL_FAILURE;

    qmiLocEditGeofenceReqMsgT_v02 editReq;
    memset(&editReq, 0, sizeof(editReq));

    editReq.geofenceId = hwId;
    editReq.transactionId = clientId;
    editReq.geofenceState_valid = 1;
    editReq.geofenceState = eQMI_LOC_GEOFENCE_STATE_SUSPEND_V02;

    LOC_SEND_SYNC_REQ(EditGeofence, EDIT_GEOFENCE, editReq);

    if (rv) {
        err = LOCATION_ERROR_SUCCESS;
    } else {
        LOC_LOGE("%s]: failed! rv is %d", __func__, rv);
    }

    if (adapterResponse != NULL) {
        adapterResponse->returnToSender(err);
    }
    }));
}

void
LocApiV02::resumeGeofence(uint32_t hwId, uint32_t clientId, LocApiResponse* adapterResponse)
{
    sendMsg(new LocApiMsg([this, hwId, clientId, adapterResponse] () {

    LOC_LOGD("%s]: hwId %u", __func__, hwId);
    LocationError err = LOCATION_ERROR_GENERAL_FAILURE;

    qmiLocEditGeofenceReqMsgT_v02 editReq;
    memset(&editReq, 0, sizeof(editReq));

    editReq.geofenceId = hwId;
    editReq.transactionId = clientId;
    editReq.geofenceState_valid = 1;
    editReq.geofenceState = eQMI_LOC_GEOFENCE_STATE_ACTIVE_V02;

    LOC_SEND_SYNC_REQ(EditGeofence, EDIT_GEOFENCE, editReq);

    if (rv) {
        err = LOCATION_ERROR_SUCCESS;
    } else {
        LOC_LOGE("%s]: failed! rv is %d", __func__, rv);
    }

    if (adapterResponse != NULL) {
        adapterResponse->returnToSender(err);
    }
    }));
}

void
LocApiV02::modifyGeofence(uint32_t hwId,
                           uint32_t clientId,
                           const GeofenceOption& options, LocApiResponse* adapterResponse)
{
    sendMsg(new LocApiMsg([this, hwId, clientId, options, adapterResponse] () {

    LOC_LOGD("%s]: breach=%u respon=%u dwell=%u",
             __func__, options.breachTypeMask, options.responsiveness, options.dwellTime);
    LocationError err = LOCATION_ERROR_GENERAL_FAILURE;

    qmiLocEditGeofenceReqMsgT_v02 editReq;
    memset(&editReq, 0, sizeof(editReq));

    editReq.geofenceId = hwId;
    editReq.transactionId = clientId;

    editReq.breachMask_valid = 1;
    if (options.breachTypeMask & GEOFENCE_BREACH_ENTER_BIT) {
        editReq.breachMask |= QMI_LOC_GEOFENCE_BREACH_ENTERING_MASK_V02;
    }
    if (options.breachTypeMask & GEOFENCE_BREACH_EXIT_BIT) {
        editReq.breachMask |= QMI_LOC_GEOFENCE_BREACH_LEAVING_MASK_V02;
    }

    editReq.responsiveness_valid = 1;
    if (options.responsiveness <= GF_RESPONSIVENESS_THRESHOLD_MSEC_HIGH) {
        editReq.responsiveness = eQMI_LOC_GEOFENCE_RESPONSIVENESS_HIGH_V02;
    } else if (options.responsiveness <= GF_RESPONSIVENESS_THRESHOLD_MSEC_MEDIUM) {
        editReq.responsiveness = eQMI_LOC_GEOFENCE_RESPONSIVENESS_MED_V02;
    } else {
        editReq.responsiveness = eQMI_LOC_GEOFENCE_RESPONSIVENESS_LOW_V02;
    }

    LOC_SEND_SYNC_REQ(EditGeofence, EDIT_GEOFENCE, editReq);

    if (rv) {
        err = LOCATION_ERROR_SUCCESS;
    } else {
        LOC_LOGE("%s]: failed! rv is %d", __func__, rv);
    }
    if (adapterResponse != NULL) {
        adapterResponse->returnToSender(err);
    }
    }));

}

void LocApiV02::setBatchSize(size_t size)
{
    LOC_LOGD("%s]: mDesiredBatchSize %zu", __func__, size);
    mDesiredBatchSize = size;
    // set to zero so the actual batch size will be queried from modem on first startBatching call
    mBatchSize = 0;
}

void LocApiV02::setTripBatchSize(size_t size)
{
    mDesiredTripBatchSize = size;
    // set to zero so the actual trip batch size will be queried from modem on
    // first startOutdoorTripBatching call
    mTripBatchSize = 0;
}

LocationError
LocApiV02::queryBatchBuffer(size_t desiredSize,
        size_t &allocatedSize, BatchingMode batchMode)
{
    LocationError err = LOCATION_ERROR_GENERAL_FAILURE;
    qmiLocGetBatchSizeReqMsgT_v02 batchSizeReq;

    memset(&batchSizeReq, 0, sizeof(batchSizeReq));
    batchSizeReq.transactionId = 1;
    batchSizeReq.batchSize = desiredSize;

    batchSizeReq.batchType_valid = 1;
    batchSizeReq.batchType = (batchMode == BATCHING_MODE_ROUTINE ? eQMI_LOC_LOCATION_BATCHING_V02 :
            eQMI_LOC_OUTDOOR_TRIP_BATCHING_V02);
    LOC_SEND_SYNC_REQ(GetBatchSize, GET_BATCH_SIZE, batchSizeReq);

    if (rv) {
        allocatedSize = ind.batchSize;
        LOC_LOGV("%s:%d]: get batching size succeeded. The modem batch size for"
                " batch mode %u is %zu. Desired batch size : %zu.",
                __func__, __LINE__, batchMode, allocatedSize, desiredSize);
        if (allocatedSize != 0) {
            err = LOCATION_ERROR_SUCCESS;
        }
    } else {
        if ((batchMode == BATCHING_MODE_TRIP) &&
            (ind.status == eQMI_LOC_INVALID_PARAMETER_V02) &&
            (ind.batchSize > 0)) {

            LOC_LOGW("%s:%d]: get batching size failed. The modem max threshold batch size "
                    "for batch mode %u is %u. Desired batch size : %zu. "
                    "Retrying with max threshold size ...",
                    __func__, __LINE__, batchMode, ind.batchSize, desiredSize);

            desiredSize = ind.batchSize;
            batchSizeReq.batchSize = ind.batchSize;
            LOC_SEND_SYNC_REQ(GetBatchSize, GET_BATCH_SIZE, batchSizeReq);

            if (rv) {
                allocatedSize = ind.batchSize;
                LOC_LOGV("%s:%d]: get batching size succeeded. The modem batch size for"
                        " batch mode %u is %zu. Desired batch size : %zu.",
                        __func__, __LINE__, batchMode, allocatedSize, desiredSize);
                if (allocatedSize != 0) {
                    err = LOCATION_ERROR_SUCCESS;
                }
                return err;
            }
        }

        allocatedSize = 0;
        LOC_LOGE("%s:%d]: get batching size failed for batch mode %u and desired batch size %zu"
                "Or modem does not support batching",
                __func__, __LINE__, batchMode, desiredSize);
    }

    return err;
}

LocationError
LocApiV02::releaseBatchBuffer(BatchingMode batchMode) {

    LocationError err = LOCATION_ERROR_GENERAL_FAILURE;

    qmiLocReleaseBatchReqMsgT_v02 batchReleaseReq;
    memset(&batchReleaseReq, 0, sizeof(batchReleaseReq));
    batchReleaseReq.transactionId = 1;

    batchReleaseReq.batchType_valid = 1;
    switch (batchMode) {
        case BATCHING_MODE_ROUTINE:
            batchReleaseReq.batchType = eQMI_LOC_LOCATION_BATCHING_V02;
        break;

        case BATCHING_MODE_TRIP:
            batchReleaseReq.batchType = eQMI_LOC_OUTDOOR_TRIP_BATCHING_V02;
        break;

        default:
            err = LOCATION_ERROR_INVALID_PARAMETER;
            LOC_LOGE("%s:%d]: release batch failed for batch mode %u",
                __func__, __LINE__, batchMode);
            return err;
    }

    LOC_SEND_SYNC_REQ(ReleaseBatch, RELEASE_BATCH, batchReleaseReq);

    if (rv) {
        LOC_LOGV("%s:%d]: release batch succeeded for batch mode %u",
                 __func__, __LINE__, batchMode);
        mTripBatchSize = 0;
        err = LOCATION_ERROR_SUCCESS;
    } else {
        LOC_LOGE("%s:%d]: release batch failed for batch mode %u",
                __func__, __LINE__, batchMode);
    }

    return err;
}


void
LocApiV02::setOperationMode(GnssSuplMode mode)
{
    locClientStatusEnumType status;
    locClientReqUnionType req_union;

    qmiLocSetOperationModeReqMsgT_v02 set_mode_msg;
    qmiLocSetOperationModeIndMsgT_v02 set_mode_ind;

    memset (&set_mode_msg, 0, sizeof(set_mode_msg));
    memset (&set_mode_ind, 0, sizeof(set_mode_ind));

    if (GNSS_SUPL_MODE_MSB == mode) {
        set_mode_msg.operationMode = eQMI_LOC_OPER_MODE_MSB_V02;
        LOC_LOGV("%s:%d]: operationMode MSB", __func__, __LINE__);
    } else if (GNSS_SUPL_MODE_MSA == mode) {
        set_mode_msg.operationMode = eQMI_LOC_OPER_MODE_MSA_V02;
        LOC_LOGV("%s:%d]: operationMode MSA", __func__, __LINE__);
    } else {
        set_mode_msg.operationMode = eQMI_LOC_OPER_MODE_STANDALONE_V02;
        LOC_LOGV("%s:%d]: operationMode STANDALONE", __func__, __LINE__);
    }

    req_union.pSetOperationModeReq = &set_mode_msg;

    status = locSyncSendReq(QMI_LOC_SET_OPERATION_MODE_REQ_V02,
                            req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT,
                            QMI_LOC_SET_OPERATION_MODE_IND_V02,
                            &set_mode_ind);

    if (eLOC_CLIENT_SUCCESS != status || eQMI_LOC_SUCCESS_V02 != set_mode_ind.status) {
        LOC_LOGE ("%s:%d]: Failed status = %d ind.status = %d",
                  __func__, __LINE__, status, set_mode_ind.status);
    }
}

void
LocApiV02::startTimeBasedTracking(const TrackingOptions& options, LocApiResponse* adapterResponse)
{
    sendMsg(new LocApiMsg([this, options, adapterResponse] () {

    LOC_LOGD("%s] minInterval %u", __func__, options.minInterval);
    LocationError err = LOCATION_ERROR_SUCCESS;

    if (!mInSession) {
        mPositionElapsedRealTimeCal.reset();
        mMeasElapsedRealTimeCal.reset();
    }

    mInSession = true;
    mMeasurementsStarted = true;
    registerEventMask(mMask);
    setOperationMode(options.mode);

    locClientStatusEnumType status;
    locClientReqUnionType req_union;
    qmiLocStartReqMsgT_v02 start_msg;
    memset(&start_msg, 0, sizeof(start_msg));

    start_msg.sessionId = 1; // dummy session id

    // interval
    uint32_t minInterval = options.minInterval;
    mMinInterval = minInterval;

    /*set interval for intermediate fixes*/
    start_msg.minIntermediatePositionReportInterval_valid = 1;
    start_msg.minIntermediatePositionReportInterval = minInterval;

    /*set interval for final fixes*/
    start_msg.minInterval_valid = 1;
    start_msg.minInterval = minInterval;

    // accuracy
    start_msg.horizontalAccuracyLevel_valid = 1;
    start_msg.horizontalAccuracyLevel = eQMI_LOC_ACCURACY_HIGH_V02;

    // recurrence
    start_msg.fixRecurrence_valid = 1;
    start_msg.fixRecurrence = eQMI_LOC_RECURRENCE_PERIODIC_V02;

    // altitude assumed
    start_msg.configAltitudeAssumed_valid = 1;
    start_msg.configAltitudeAssumed =
        eQMI_LOC_ALTITUDE_ASSUMED_IN_GNSS_SV_INFO_DISABLED_V02;

    // power mode
    if (GNSS_POWER_MODE_INVALID != options.powerMode) {
        start_msg.powerMode_valid = 1;
        start_msg.powerMode.powerMode =
                convertPowerMode(options.powerMode);
        start_msg.powerMode.timeBetweenMeasurement = options.tbm;
        // Force low accuracy for background power modes
        if (GNSS_POWER_MODE_M3 == options.powerMode ||
                GNSS_POWER_MODE_M4 == options.powerMode ||
                GNSS_POWER_MODE_M5 == options.powerMode) {
            start_msg.horizontalAccuracyLevel =  eQMI_LOC_ACCURACY_LOW_V02;
        }
        // Force TBM = TBF for power mode M4
        if (GNSS_POWER_MODE_M4 == options.powerMode) {
            start_msg.powerMode.timeBetweenMeasurement = start_msg.minInterval;
        }
    }

    req_union.pStartReq = &start_msg;
    status = locClientSendReq(QMI_LOC_START_REQ_V02, req_union);
    if (eLOC_CLIENT_SUCCESS != status) {
        LOC_LOGE ("%s]: failed! status %d",
                  __func__, status);
        err = LOCATION_ERROR_GENERAL_FAILURE;
    }

    if (adapterResponse != NULL) {
        adapterResponse->returnToSender(err);
    }
    }));
}

void LocApiV02::configConstellationMultiBand(const GnssSvTypeConfig& secondaryBandConfig,
                                             LocApiResponse* adapterResponse) {

    sendMsg(new LocApiMsg([this, secondaryBandConfig, adapterResponse] () {

    LocationError err = LOCATION_ERROR_SUCCESS;
    locClientStatusEnumType status = eLOC_CLIENT_FAILURE_GENERAL;
    locClientReqUnionType req_union = {};

    qmiLocSetMultibandConfigReqMsgT_v02 reqMsg = {};
    qmiLocGenReqStatusIndMsgT_v02 genReqStatusIndMsg = {};

    // Fill in the request details
    reqMsg.secondaryGnssConfig_valid = true;
    if (secondaryBandConfig.enabledSvTypesMask & GNSS_SV_TYPES_MASK_GPS_BIT) {
        reqMsg.secondaryGnssConfig |= eQMI_SYSTEM_GPS_V02;
    }
    if (secondaryBandConfig.enabledSvTypesMask & GNSS_SV_TYPES_MASK_GLO_BIT) {
        reqMsg.secondaryGnssConfig |= eQMI_SYSTEM_GLO_V02;
    }
    if (secondaryBandConfig.enabledSvTypesMask & GNSS_SV_TYPES_MASK_BDS_BIT) {
        reqMsg.secondaryGnssConfig |= eQMI_SYSTEM_BDS_V02;
    }
    if (secondaryBandConfig.enabledSvTypesMask & GNSS_SV_TYPES_MASK_QZSS_BIT) {
        reqMsg.secondaryGnssConfig |= eQMI_SYSTEM_QZSS_V02;
    }
    if (secondaryBandConfig.enabledSvTypesMask & GNSS_SV_TYPES_MASK_GAL_BIT) {
        reqMsg.secondaryGnssConfig |= eQMI_SYSTEM_GAL_V02;
    }
    if (secondaryBandConfig.enabledSvTypesMask & GNSS_SV_TYPES_MASK_NAVIC_BIT) {
        reqMsg.secondaryGnssConfig |= eQMI_SYSTEM_NAVIC_V02;
    }

    LOC_LOGd("hal secondary band enabled constellation: 0x%" PRIx64 ", "
             "qmi secondary band disabed constellation: 0x%" PRIx64 "",
             secondaryBandConfig.enabledSvTypesMask, reqMsg.secondaryGnssConfig);

    // Update in request union
    req_union.pSetMultibandConfigReq = &reqMsg;

    // Send the request
    status = loc_sync_send_req(clientHandle,
                               QMI_LOC_SET_MULTIBAND_CONFIG_REQ_V02,
                               req_union,
                               LOC_ENGINE_SYNC_REQUEST_TIMEOUT,
                               QMI_LOC_SET_MULTIBAND_CONFIG_IND_V02,
                               &genReqStatusIndMsg);
    if (status != eLOC_CLIENT_SUCCESS ||
            genReqStatusIndMsg.status != eQMI_LOC_SUCCESS_V02) {
        LOC_LOGe("Config multiband failed. status: %s ind status %s",
                 loc_get_v02_client_status_name(status),
                 loc_get_v02_qmi_status_name(genReqStatusIndMsg.status));

        if (status == eLOC_CLIENT_FAILURE_UNSUPPORTED ||
                status == eLOC_CLIENT_FAILURE_INVALID_MESSAGE_ID) {
            err = LOCATION_ERROR_NOT_SUPPORTED;
        } else {
            err = LOCATION_ERROR_GENERAL_FAILURE;
        }
    }

    if (adapterResponse) {
        adapterResponse->returnToSender(err);
    }
    }));
}

void LocApiV02::getConstellationMultiBandConfig(
        uint32_t sessionId, LocApiResponse* adapterResponse) {

    sendMsg(new LocApiMsg([this, sessionId, adapterResponse] () {

    LocationError err = LOCATION_ERROR_SUCCESS;
    locClientStatusEnumType status = eLOC_CLIENT_FAILURE_GENERAL;
    locClientReqUnionType req_union = {};

    qmiLocGetConstellationConfigIndMsgT_v02 getConstellationConfigInd = {};
    qmiLocGetBlacklistSvIndMsgT_v02 getBlacklistSvConfigInd = {};
    qmiLocGetMultibandConfigIndMsgT_v02 getMultibandConfigInd = {};
    GnssConfig gnssConfig = {};

    // get multiband config
    status = locSyncSendReq(QMI_LOC_GET_MULTIBAND_CONFIG_REQ_V02,
                            req_union, LOC_ENGINE_SYNC_REQUEST_LONG_TIMEOUT,
                            QMI_LOC_GET_MULTIBAND_CONFIG_IND_V02,
                            &getMultibandConfigInd);
    if ((status == eLOC_CLIENT_SUCCESS) && (getMultibandConfigInd.status == eQMI_LOC_SUCCESS_V02) &&
            getMultibandConfigInd.secondaryGnssConfig_valid) {
        convertQmiSecondaryConfigToGnssConfig(getMultibandConfigInd.secondaryGnssConfig,
                                              gnssConfig.secondaryBandConfig);
        gnssConfig.flags |= GNSS_CONFIG_FLAGS_CONSTELLATION_SECONDARY_BAND_BIT;
    } else {
        LOC_LOGe("Get multiband config failed. status: %s, ind status:%s",
                 loc_get_v02_client_status_name(status),
                 loc_get_v02_qmi_status_name(getMultibandConfigInd.status));

        if (status == eLOC_CLIENT_FAILURE_UNSUPPORTED ||
                status == eLOC_CLIENT_FAILURE_INVALID_MESSAGE_ID) {
            err = LOCATION_ERROR_NOT_SUPPORTED;
        } else {
            err = LOCATION_ERROR_GENERAL_FAILURE;
        }
    }

    if (gnssConfig.flags) {
        LocApiBase::reportGnssConfig(sessionId, gnssConfig);
    } else {
        if (err != LOCATION_ERROR_NOT_SUPPORTED) {
            err = LOCATION_ERROR_GENERAL_FAILURE;
        }
        adapterResponse->returnToSender(err);
    }

    LOC_LOGd("Exit. err: %u", err);
    }));
}


void LocApiV02::convertQmiSecondaryConfigToGnssConfig(
        qmiLocGNSSConstellEnumT_v02 qmiSecondaryBandConfig,
        GnssSvTypeConfig& secondaryBandConfig) {

    LOC_LOGd("qmi secondary band config: 0x%" PRIx64 "", qmiSecondaryBandConfig);
    memset(&secondaryBandConfig, 0, sizeof(secondaryBandConfig));
    secondaryBandConfig.size = sizeof(secondaryBandConfig);

    if (qmiSecondaryBandConfig & eQMI_SYSTEM_GPS_V02) {
        secondaryBandConfig.enabledSvTypesMask |= GNSS_SV_TYPES_MASK_GPS_BIT;
    }
    if (qmiSecondaryBandConfig & eQMI_SYSTEM_GLO_V02) {
        secondaryBandConfig.enabledSvTypesMask |= GNSS_SV_TYPES_MASK_GLO_BIT;
    }
    if (qmiSecondaryBandConfig &eQMI_SYSTEM_BDS_V02) {
        secondaryBandConfig.enabledSvTypesMask |= GNSS_SV_TYPES_MASK_BDS_BIT;
    }
    if (qmiSecondaryBandConfig & eQMI_SYSTEM_QZSS_V02) {
        secondaryBandConfig.enabledSvTypesMask |= GNSS_SV_TYPES_MASK_QZSS_BIT;
    }
    if (qmiSecondaryBandConfig & eQMI_SYSTEM_GAL_V02) {
        secondaryBandConfig.enabledSvTypesMask |= GNSS_SV_TYPES_MASK_GAL_BIT;
    }
    if (qmiSecondaryBandConfig & eQMI_SYSTEM_NAVIC_V02) {
        secondaryBandConfig.enabledSvTypesMask |= GNSS_SV_TYPES_MASK_NAVIC_BIT;
    }

    secondaryBandConfig.blacklistedSvTypesMask =
            (~secondaryBandConfig.enabledSvTypesMask & GNSS_SV_TYPES_MASK_ALL);
}

void LocApiV02::convertQmiBlacklistedSvConfigToGnssConfig(
        const qmiLocGetBlacklistSvIndMsgT_v02& qmiBlacklistConfig,
        GnssSvIdConfig& gnssBlacklistConfig) {

    GnssSvIdConfig svConfig = {};
    gnssBlacklistConfig.size = sizeof(gnssBlacklistConfig);

    if (qmiBlacklistConfig.glo_persist_blacklist_sv_valid) {
        gnssBlacklistConfig.gloBlacklistSvMask = qmiBlacklistConfig.glo_persist_blacklist_sv;
    }

    if (qmiBlacklistConfig.bds_persist_blacklist_sv_valid) {
        gnssBlacklistConfig.bdsBlacklistSvMask = qmiBlacklistConfig.bds_persist_blacklist_sv;
    }

    if (qmiBlacklistConfig.qzss_persist_blacklist_sv_valid) {
        gnssBlacklistConfig.qzssBlacklistSvMask = qmiBlacklistConfig.qzss_persist_blacklist_sv;
    }

    if (qmiBlacklistConfig.gal_persist_blacklist_sv_valid) {
        gnssBlacklistConfig.galBlacklistSvMask = qmiBlacklistConfig.gal_persist_blacklist_sv;
    }

    if (qmiBlacklistConfig.sbas_persist_blacklist_sv_valid) {
        gnssBlacklistConfig.sbasBlacklistSvMask = qmiBlacklistConfig.sbas_persist_blacklist_sv;
    }

    if (qmiBlacklistConfig.navic_persist_blacklist_sv_valid) {
        gnssBlacklistConfig.navicBlacklistSvMask = qmiBlacklistConfig.navic_persist_blacklist_sv;
    }

    LOC_LOGd("%d %d %d %d %d %d , blacklist bds 0x%" PRIx64 ", "
             "glo 0x%" PRIx64", qzss 0x%" PRIx64 ", "
             "gal 0x%" PRIx64 ", sbas 0x%" PRIx64 ", "
             "navic 0x%" PRIx64 "",
             qmiBlacklistConfig.glo_persist_blacklist_sv_valid,
             qmiBlacklistConfig.bds_persist_blacklist_sv_valid,
             qmiBlacklistConfig.qzss_persist_blacklist_sv_valid,
             qmiBlacklistConfig.gal_persist_blacklist_sv_valid,
             qmiBlacklistConfig.sbas_persist_blacklist_sv_valid,
             qmiBlacklistConfig.navic_persist_blacklist_sv_valid,
             gnssBlacklistConfig.bdsBlacklistSvMask, gnssBlacklistConfig.gloBlacklistSvMask,
             gnssBlacklistConfig.qzssBlacklistSvMask, gnssBlacklistConfig.galBlacklistSvMask,
             gnssBlacklistConfig.sbasBlacklistSvMask, gnssBlacklistConfig.navicBlacklistSvMask);
}

qmiLocPowerModeEnumT_v02
LocApiV02::convertPowerMode(GnssPowerMode powerMode)
{
    switch(powerMode) {
    case GNSS_POWER_MODE_M1:
        return eQMI_LOC_POWER_MODE_IMPROVED_ACCURACY_V02;
    case GNSS_POWER_MODE_M2:
        return eQMI_LOC_POWER_MODE_NORMAL_V02;
    case GNSS_POWER_MODE_M3:
        return eQMI_LOC_POWER_MODE_BACKGROUND_DEFINED_POWER_V02;
    case GNSS_POWER_MODE_M4:
        return eQMI_LOC_POWER_MODE_BACKGROUND_DEFINED_TIME_V02;
    case GNSS_POWER_MODE_M5:
        return eQMI_LOC_POWER_MODE_BACKGROUND_KEEP_WARM_V02;
    default:
        LOC_LOGE("Invalid power mode %d", powerMode);
    }

    return QMILOCPOWERMODEENUMT_MIN_ENUM_VAL_V02;
}

void
LocApiV02::stopTimeBasedTracking(LocApiResponse* adapterResponse)
{
    sendMsg(new LocApiMsg([this, adapterResponse] () {

    LOC_LOGD("%s] ", __func__);
    LocationError err = LOCATION_ERROR_SUCCESS;

    locClientStatusEnumType status;
    locClientReqUnionType req_union;
    qmiLocStopReqMsgT_v02 stop_msg;
    memset(&stop_msg, 0, sizeof(stop_msg));
    stop_msg.sessionId = 1; // dummy session id
    req_union.pStopReq = &stop_msg;

    status = locClientSendReq(QMI_LOC_STOP_REQ_V02, req_union);
    if (status != eLOC_CLIENT_SUCCESS) {
        LOC_LOGE ("%s]: failed! status %d",
                  __func__, status);
        err = LOCATION_ERROR_GENERAL_FAILURE;
    } else {
        mInSession = false;
        mPowerMode = GNSS_POWER_MODE_INVALID;

        // if engine on never happend, deregister events
        // without waiting for Engine Off
        if (!mEngineOn) {
            registerEventMask(mMask);
        }
    }

    if (adapterResponse != NULL) {
        adapterResponse->returnToSender(err);
    }
    }));
}

void
LocApiV02::startDistanceBasedTracking(uint32_t sessionId,
                                       const LocationOptions& options,
                                       LocApiResponse* adapterResponse)
{
    sendMsg(new LocApiMsg([this, sessionId, options, adapterResponse] () {

    LOC_LOGD("%s] id %u minInterval %u minDistance %u",
             __func__, sessionId, options.minInterval, options.minDistance);
    LocationError err = LOCATION_ERROR_SUCCESS;

    /** start distance based tracking session*/
    locClientStatusEnumType status;
    locClientReqUnionType req_union;
    qmiLocStartDbtReqMsgT_v02 start_dbt_req;
    qmiLocStartDbtIndMsgT_v02 start_dbt_ind;
    memset(&start_dbt_req, 0, sizeof(start_dbt_req));
    memset(&start_dbt_ind, 0, sizeof(start_dbt_ind));

    // request id
    start_dbt_req.reqId = sessionId;

    // distance
    start_dbt_req.minDistance = options.minDistance;

    // time
    uint32_t minInterval = options.minInterval;
    start_dbt_req.maxLatency_valid = 1;
    start_dbt_req.maxLatency = minInterval/1000; //in seconds
    if (0 == start_dbt_req.maxLatency) {
        start_dbt_req.maxLatency = 1; //in seconds
    }

    // type
    start_dbt_req.distanceType = eQMI_LOC_DBT_DISTANCE_TYPE_STRAIGHT_LINE_V02;

    /* original location disabled by default, as the original location is
       the one cached in the modem buffer and its timestamps is not fresh.*/
    start_dbt_req.needOriginLocation = 0;

    start_dbt_req.usageType_valid = 1;
    start_dbt_req.usageType = eQMI_LOC_DBT_USAGE_NAVIGATION_V02;
    req_union.pStartDbtReq = &start_dbt_req;

    status = locSyncSendReq(QMI_LOC_START_DBT_REQ_V02,
                            req_union,
                            LOC_ENGINE_SYNC_REQUEST_TIMEOUT,
                            QMI_LOC_START_DBT_IND_V02,
                            &start_dbt_ind);

    if (eLOC_CLIENT_SUCCESS != status ||
        eQMI_LOC_SUCCESS_V02 != start_dbt_ind.status) {
        LOC_LOGE("%s] failed! status %d ind.status %d",
              __func__, status, start_dbt_ind.status);
    }

    if (adapterResponse != NULL) {
        adapterResponse->returnToSender(err);
    }
    }));
}

void
LocApiV02::stopDistanceBasedTracking(uint32_t sessionId, LocApiResponse* adapterResponse)
{
    sendMsg(new LocApiMsg([this, sessionId, adapterResponse] () {

    LOC_LOGD("%s] id %u", __func__, sessionId);
    LocationError err = LOCATION_ERROR_SUCCESS;

    locClientStatusEnumType status;
    locClientReqUnionType req_union;
    qmiLocStopDbtReqMsgT_v02 stop_dbt_req;
    qmiLocStopDbtIndMsgT_v02 stop_dbt_Ind;
    memset(&stop_dbt_req, 0, sizeof(stop_dbt_req));
    memset(&stop_dbt_Ind, 0, sizeof(stop_dbt_Ind));

    stop_dbt_req.reqId = sessionId;

    req_union.pStopDbtReq = &stop_dbt_req;

    status = locSyncSendReq(QMI_LOC_STOP_DBT_REQ_V02,
                            req_union,
                            LOC_ENGINE_SYNC_REQUEST_TIMEOUT,
                            QMI_LOC_STOP_DBT_IND_V02,
                            &stop_dbt_Ind);

    if (eLOC_CLIENT_SUCCESS != status ||
        eQMI_LOC_SUCCESS_V02 != stop_dbt_Ind.status) {
        LOC_LOGE("%s] failed! status %d ind.status %d",
              __func__, status, stop_dbt_Ind.status);
    }

    adapterResponse->returnToSender(err);
    }));
}

void
LocApiV02::startBatching(uint32_t sessionId,
                          const LocationOptions& options,
                          uint32_t accuracy,
                          uint32_t timeout,
                          LocApiResponse* adapterResponse)
{
    sendMsg(new LocApiMsg([this, sessionId, options, accuracy, timeout, adapterResponse] () {

    LOC_LOGD("%s]: id %u minInterval %u minDistance %u accuracy %u timeout %u",
             __func__, sessionId, options.minInterval, options.minDistance, accuracy, timeout);
    LocationError err = LOCATION_ERROR_SUCCESS;

    setOperationMode(options.mode);

    //get batch size if needs
    if (mBatchSize == 0) {
        if (LOCATION_ERROR_SUCCESS != queryBatchBuffer(mDesiredBatchSize,
                mBatchSize, BATCHING_MODE_ROUTINE)) {
            if (adapterResponse != NULL) {
                adapterResponse->returnToSender(LOCATION_ERROR_GENERAL_FAILURE);
            }
            return;
        }
    }

    qmiLocStartBatchingReqMsgT_v02 startBatchReq;
    memset(&startBatchReq, 0, sizeof(startBatchReq));

    // interval
    startBatchReq.minInterval_valid = 1;
    if (options.minInterval >= FLP_BATCHING_MINIMUN_INTERVAL) {
        startBatchReq.minInterval = options.minInterval;
    } else {
        startBatchReq.minInterval = FLP_BATCHING_MINIMUN_INTERVAL; // 1 second
    }

    // distance
    startBatchReq.minDistance_valid = 1;
    startBatchReq.minDistance = options.minDistance;

    // accuracy
    startBatchReq.horizontalAccuracyLevel_valid = 1;
    switch(accuracy) {
    case 0:
        startBatchReq.horizontalAccuracyLevel = eQMI_LOC_ACCURACY_LOW_V02;
        break;
    case 1:
        startBatchReq.horizontalAccuracyLevel = eQMI_LOC_ACCURACY_MED_V02;
        break;
    case 2:
        startBatchReq.horizontalAccuracyLevel = eQMI_LOC_ACCURACY_HIGH_V02;
        break;
    default:
        startBatchReq.horizontalAccuracyLevel = eQMI_LOC_ACCURACY_LOW_V02;
    }

    // time out
    if (timeout > 0) {
        startBatchReq.fixSessionTimeout_valid = 1;
        startBatchReq.fixSessionTimeout = timeout;
    } else {
        // modem will use the default time out (20 seconds)
        startBatchReq.fixSessionTimeout_valid = 0;
    }

    // batch request id
    startBatchReq.requestId_valid = 1;
    startBatchReq.requestId = sessionId;

    // batch all fixes always
    startBatchReq.batchAllPos_valid = 1;
    startBatchReq.batchAllPos = true;

    LOC_SEND_SYNC_REQ(StartBatching, START_BATCHING, startBatchReq);

    if (!rv) {
        LOC_LOGE("%s] failed!", __func__);
        err = LOCATION_ERROR_GENERAL_FAILURE;
    }

    if (adapterResponse != NULL) {
        adapterResponse->returnToSender(err);
    }

    }));
}

void
LocApiV02::stopBatching(uint32_t sessionId, LocApiResponse* adapterResponse)
{
    sendMsg(new LocApiMsg([this, sessionId, adapterResponse] () {

    LOC_LOGD("%s] id %u", __func__, sessionId);
    LocationError err = LOCATION_ERROR_SUCCESS;

    locClientStatusEnumType status;

    qmiLocStopBatchingReqMsgT_v02 stopBatchingReq;
    memset(&stopBatchingReq, 0, sizeof(stopBatchingReq));

    stopBatchingReq.requestId_valid = 1;
    stopBatchingReq.requestId = sessionId;

    stopBatchingReq.batchType_valid = 1;
    stopBatchingReq.batchType = eQMI_LOC_LOCATION_BATCHING_V02;

    LOC_SEND_SYNC_REQ(StopBatching, STOP_BATCHING, stopBatchingReq);

    if (!rv) {
        LOC_LOGE("%s] failed!", __func__);
        err = LOCATION_ERROR_GENERAL_FAILURE;
    }
    if (adapterResponse != NULL) {
        adapterResponse->returnToSender(err);
    }
    }));
}

LocationError
LocApiV02::startOutdoorTripBatchingSync(uint32_t tripDistance, uint32_t tripTbf, uint32_t timeout)
{
    LOC_LOGD("%s]: minInterval %u minDistance %u timeout %u",
             __func__, tripTbf, tripDistance, timeout);
    LocationError err = LOCATION_ERROR_SUCCESS;

    //get batch size if needs
    if (mTripBatchSize == 0) {
        if (LOCATION_ERROR_SUCCESS != queryBatchBuffer(mDesiredTripBatchSize,
            mTripBatchSize, BATCHING_MODE_TRIP)) {
            return LOCATION_ERROR_GENERAL_FAILURE;
        }
    }

    qmiLocStartOutdoorTripBatchingReqMsgT_v02 startOutdoorTripBatchReq;
    memset(&startOutdoorTripBatchReq, 0, sizeof(startOutdoorTripBatchReq));

    if (tripDistance > 0) {
        startOutdoorTripBatchReq.batchDistance = tripDistance;
    } else {
        startOutdoorTripBatchReq.batchDistance = FLP_BATCHING_MIN_TRIP_DISTANCE; // 1 meter
    }

    if (tripTbf >= FLP_BATCHING_MINIMUN_INTERVAL) {
        startOutdoorTripBatchReq.minTimeInterval = tripTbf;
    } else {
        startOutdoorTripBatchReq.minTimeInterval = FLP_BATCHING_MINIMUN_INTERVAL; // 1 second
    }

    // batch all fixes always
    startOutdoorTripBatchReq.batchAllPos_valid = 1;
    startOutdoorTripBatchReq.batchAllPos = true;

    // time out
    if (timeout > 0) {
        startOutdoorTripBatchReq.fixSessionTimeout_valid = 1;
        startOutdoorTripBatchReq.fixSessionTimeout = timeout;
    } else {
        // modem will use the default time out (20 seconds)
        startOutdoorTripBatchReq.fixSessionTimeout_valid = 0;
    }

    LOC_SEND_SYNC_REQ(StartOutdoorTripBatching, START_OUTDOOR_TRIP_BATCHING,
            startOutdoorTripBatchReq);

    if (!rv) {
        LOC_LOGE("%s] failed!", __func__);
        err = LOCATION_ERROR_GENERAL_FAILURE;
    }

    return err;
}

void
LocApiV02::startOutdoorTripBatching(uint32_t tripDistance, uint32_t tripTbf, uint32_t timeout,
                                          LocApiResponse* adapterResponse) {
    sendMsg(new LocApiMsg([this, tripDistance, tripTbf, timeout, adapterResponse] () {
        if (adapterResponse != NULL) {
            adapterResponse->returnToSender(startOutdoorTripBatchingSync(tripDistance,
                                                                         tripTbf,
                                                                         timeout));
        }
    }));
}

void
LocApiV02::reStartOutdoorTripBatching(uint32_t ongoingTripDistance,
                                            uint32_t ongoingTripInterval,
                                            uint32_t batchingTimeout,
                                            LocApiResponse* adapterResponse)
{
    sendMsg(new LocApiMsg([this, ongoingTripDistance, ongoingTripInterval, batchingTimeout,
                           adapterResponse] () {
        LocationError err = LOCATION_ERROR_SUCCESS;

        uint32_t accumulatedDistance = 0;
        uint32_t numOfBatchedPositions = 0;
        queryAccumulatedTripDistanceSync(accumulatedDistance, numOfBatchedPositions);

        if (numOfBatchedPositions) {
            getBatchedTripLocationsSync(numOfBatchedPositions, 0);
        }

        stopOutdoorTripBatchingSync(false);

        err = startOutdoorTripBatchingSync(ongoingTripDistance,
                                           ongoingTripInterval,
                                           batchingTimeout);
        if (adapterResponse != NULL) {
            adapterResponse->returnToSender(err);
        }
    }));
}

LocationError
LocApiV02::stopOutdoorTripBatchingSync(bool deallocBatchBuffer)
{
    LOC_LOGD("%s] dellocBatchBuffer : %d", __func__, deallocBatchBuffer);
    LocationError err = LOCATION_ERROR_SUCCESS;

    locClientStatusEnumType status;

    qmiLocStopBatchingReqMsgT_v02 stopBatchingReq;
    memset(&stopBatchingReq, 0, sizeof(stopBatchingReq));

    stopBatchingReq.batchType_valid = 1;
    stopBatchingReq.batchType = eQMI_LOC_OUTDOOR_TRIP_BATCHING_V02;
    LOC_SEND_SYNC_REQ(StopBatching, STOP_BATCHING, stopBatchingReq);

    if (!rv) {
        LOC_LOGE("%s] failed!", __func__);
        err = LOCATION_ERROR_GENERAL_FAILURE;
        return err;
    }

    if (deallocBatchBuffer) {
        err = releaseBatchBuffer(BATCHING_MODE_TRIP);
    }

    return err;
}

void
LocApiV02::stopOutdoorTripBatching(bool deallocBatchBuffer, LocApiResponse* adapterResponse)
{
    sendMsg(new LocApiMsg([this, deallocBatchBuffer, adapterResponse] () {
        if (adapterResponse != NULL) {
            adapterResponse->returnToSender(stopOutdoorTripBatchingSync(deallocBatchBuffer));
        }
    }));
}

LocationError
LocApiV02::getBatchedLocationsSync(size_t count)
{
    LOC_LOGD("%s] count %zu.", __func__, count);
    LocationError err = LOCATION_ERROR_SUCCESS;

    size_t entriesToReadInTotal = std::min(mBatchSize,count);
    if (entriesToReadInTotal == 0) {
        LOC_LOGD("%s] No batching memory allocated in modem or nothing to read", __func__);
        // calling the base class
        reportLocations(NULL, 0, BATCHING_MODE_ROUTINE);
    } else {
        size_t entriesToRead =
            std::min(entriesToReadInTotal, (size_t)QMI_LOC_READ_FROM_BATCH_MAX_SIZE_V02);
        size_t entriesGotInTotal = 0;
        size_t entriesGotInEachTime = 0;
        //allocate +1 just in case we get one more location added during read
        Location* pLocationsFromModem = new Location[entriesToReadInTotal+1]();
        if (pLocationsFromModem == nullptr) {
            LOC_LOGE("new allocation failed, fatal error.");
            return LOCATION_ERROR_GENERAL_FAILURE;
        }
        memset(pLocationsFromModem, 0, sizeof(Location)*(entriesToReadInTotal+1));
        Location* tempLocationP = new Location[QMI_LOC_READ_FROM_BATCH_MAX_SIZE_V02]();
        if (tempLocationP == nullptr) {
            LOC_LOGE("new allocation failed, fatal error.");
            return LOCATION_ERROR_GENERAL_FAILURE;
        }
        do {
            memset(tempLocationP, 0, QMI_LOC_READ_FROM_BATCH_MAX_SIZE_V02*sizeof(Location));
            readModemLocations(tempLocationP,
                               entriesToRead,
                               BATCHING_MODE_ROUTINE,
                               entriesGotInEachTime);
            for (size_t i = 0; i<entriesGotInEachTime; i++) {
                size_t index = entriesToReadInTotal-entriesGotInTotal-i;

                // make sure index is not too large or small to fit in the array
                if (index <= entriesToReadInTotal && (int)index >= 0) {
                    pLocationsFromModem[index] = tempLocationP[i];
                } else {
                    LOC_LOGW("%s] dropped an unexpected location.", __func__);
                }
            }
            entriesGotInTotal += entriesGotInEachTime;
            entriesToRead = std::min(entriesToReadInTotal - entriesGotInTotal,
                                     (size_t)QMI_LOC_READ_FROM_BATCH_MAX_SIZE_V02);
        } while (entriesGotInEachTime > 0 && entriesToRead > 0);
        delete[] tempLocationP;

        LOC_LOGD("%s] Read out %zu batched locations from modem in total.",
                 __func__, entriesGotInTotal);

        // offset is by default 1 because we allocated one extra location during read
        uint32_t offset = 1;
        if (entriesToReadInTotal > entriesGotInTotal) {
            offset = 1 + entriesToReadInTotal - entriesGotInTotal;
            LOC_LOGD("%s] offset %u", __func__, offset);
        } else if (entriesGotInTotal > entriesToReadInTotal) {
            // offset is zero because we need one extra slot for the extra location
            offset = 0;
            LOC_LOGD("%s] Read %zu extra location(s) than expected.",
                     __func__, entriesGotInTotal - entriesToReadInTotal);
            // we got one extra location added during modem read, so one location will
            // be out of order and needs to be found and put in order
            int64_t currentTimeStamp = pLocationsFromModem[entriesToReadInTotal].timestamp;
            for (int i=entriesToReadInTotal-1; i >= 0; i--) {
                // find the out of order location
                if (currentTimeStamp < pLocationsFromModem[i].timestamp) {
                    LOC_LOGD("%s] Out of order location is index %d timestamp %" PRIu64,
                             __func__, i, pLocationsFromModem[i].timestamp);
                    // save the out of order location to be put at end of array
                    Location tempLocation(pLocationsFromModem[i]);
                    // shift the remaining locations down one
                    for (size_t j=i; j<entriesToReadInTotal; j++) {
                        pLocationsFromModem[j] = pLocationsFromModem[j+1];
                    }
                    // put the out of order location at end of array now
                    pLocationsFromModem[entriesToReadInTotal] = tempLocation;
                    break;
                } else {
                    currentTimeStamp = pLocationsFromModem[i].timestamp;
                }
            }
        }

        LOC_LOGD("%s] Calling reportLocations with count:%zu and entriesGotInTotal:%zu",
                  __func__, count, entriesGotInTotal);

        // calling the base class
        reportLocations(pLocationsFromModem+offset, entriesGotInTotal, BATCHING_MODE_ROUTINE);
        delete[] pLocationsFromModem;
    }
    return err;

}

void
LocApiV02::getBatchedLocations(size_t count, LocApiResponse* adapterResponse)
{
    sendMsg(new LocApiMsg([this, count, adapterResponse] () {
          if (adapterResponse != NULL) {
              adapterResponse->returnToSender(getBatchedLocationsSync(count));
          }
    }));
}

LocationError LocApiV02::getBatchedTripLocationsSync(size_t count, uint32_t accumulatedDistance)
{
    LocationError err = LOCATION_ERROR_SUCCESS;
    size_t idxLocationFromModem = 0;

    size_t entriesToReadInTotal = std::min(mTripBatchSize, count);
    if (entriesToReadInTotal == 0) {
        LOC_LOGD("%s] No trip batching memory allocated in modem or nothing to read", __func__);
        // calling the base class
        reportLocations(NULL, 0, BATCHING_MODE_TRIP);
    } else {
        size_t entriesToRead =
                std::min(entriesToReadInTotal, (size_t)QMI_LOC_READ_FROM_BATCH_MAX_SIZE_V02);
        size_t entriesGotInTotal = 0;
        size_t entriesGotInEachTime = 0;

        Location* pLocationsFromModem = new Location[entriesToReadInTotal]();
        if (pLocationsFromModem == nullptr) {
            LOC_LOGE("new allocation failed, fatal error.");
            return LOCATION_ERROR_GENERAL_FAILURE;
        }
        memset(pLocationsFromModem, 0, sizeof(Location)*(entriesToReadInTotal));
        Location* tempLocationP = new Location[QMI_LOC_READ_FROM_BATCH_MAX_SIZE_V02]();
        if (tempLocationP == nullptr) {
            LOC_LOGE("new allocation failed, fatal error.");
            return LOCATION_ERROR_GENERAL_FAILURE;
        }

        do {
            memset(tempLocationP, 0, QMI_LOC_READ_FROM_BATCH_MAX_SIZE_V02*sizeof(Location));
            readModemLocations(tempLocationP,
                               entriesToRead,
                               BATCHING_MODE_TRIP,
                               entriesGotInEachTime);
            for (size_t iEntryIndex = 0; iEntryIndex<entriesGotInEachTime;
                    iEntryIndex++, idxLocationFromModem++) {
                // make sure index is not too large fit in the array
                if (idxLocationFromModem < entriesToReadInTotal) {
                    pLocationsFromModem[idxLocationFromModem] = tempLocationP[iEntryIndex];
                } else {
                    LOC_LOGW("%s] dropped an unexpected location.", __func__);
                }
            }
            entriesGotInTotal += entriesGotInEachTime;
            entriesToRead = std::min(entriesToReadInTotal - entriesGotInTotal,
                                     (size_t)QMI_LOC_READ_FROM_BATCH_MAX_SIZE_V02);
        } while (entriesGotInEachTime > 0 && entriesToRead > 0);
        delete[] tempLocationP;

        LOC_LOGD("%s] Calling reportLocations with count:%zu and entriesGotInTotal:%zu",
                  __func__, count, entriesGotInTotal);

        // calling the base class
        reportLocations(pLocationsFromModem, entriesGotInTotal, BATCHING_MODE_TRIP);

        if (accumulatedDistance != 0) {
            LOC_LOGD("%s] Calling reportCompletedTrips with distance %u:",
                    __func__, accumulatedDistance);
            reportCompletedTrips(accumulatedDistance);
        }

        delete[] pLocationsFromModem;
    }

    return err;
}

void LocApiV02::getBatchedTripLocations(size_t count, uint32_t accumulatedDistance,
                                              LocApiResponse* adapterResponse)
{
    sendMsg(new LocApiMsg([this, count, accumulatedDistance, adapterResponse] () {
        if (adapterResponse != NULL) {
            adapterResponse->returnToSender(getBatchedTripLocationsSync(count, accumulatedDistance));
        }
    }));
}

void
LocApiV02::readModemLocations(Location* pLocationPiece,
                              size_t count,
                              BatchingMode batchingMode,
                              size_t& numbOfEntries)
{
    LOC_LOGD("%s] count %zu.", __func__, count);
    numbOfEntries = 0;
    qmiLocReadFromBatchReqMsgT_v02 getBatchLocatonReq;
    memset(&getBatchLocatonReq, 0, sizeof(getBatchLocatonReq));

    if (count != 0) {
        getBatchLocatonReq.numberOfEntries = count;
        getBatchLocatonReq.transactionId = 1;
    }

    getBatchLocatonReq.batchType_valid = 1;
    getBatchLocatonReq.batchType = ((batchingMode == BATCHING_MODE_ROUTINE) ?
            eQMI_LOC_LOCATION_BATCHING_V02: eQMI_LOC_OUTDOOR_TRIP_BATCHING_V02);

    LOC_SEND_SYNC_REQ(ReadFromBatch, READ_FROM_BATCH, getBatchLocatonReq);

    if (!rv) {
        LOC_LOGE("%s] Reading batched locations from modem failed.", __func__);
        return;
    }
    if (ind.numberOfEntries_valid != 0 &&
        ind.batchedReportList_valid != 0) {
        for (uint32_t i=0; i<ind.numberOfEntries; i++) {
            Location temp;
            memset (&temp, 0, sizeof(temp));
            temp.size = sizeof(Location);
            if ((ind.batchedReportList[i].validFields &
                 QMI_LOC_BATCHED_REPORT_MASK_VALID_LATITUDE_V02) &&
                (ind.batchedReportList[i].validFields &
                 QMI_LOC_BATCHED_REPORT_MASK_VALID_LONGITUDE_V02)) {
                temp.latitude = ind.batchedReportList[i].latitude;
                temp.longitude = ind.batchedReportList[i].longitude;
                temp.flags |= LOCATION_HAS_LAT_LONG_BIT;
            }
            if (ind.batchedReportList[i].validFields &
                QMI_LOC_BATCHED_REPORT_MASK_VALID_ALT_WRT_ELP_V02) {
                temp.altitude = ind.batchedReportList[i].altitudeWrtEllipsoid;
                temp.flags |= LOCATION_HAS_ALTITUDE_BIT;
            }
            if (ind.batchedReportList[i].validFields &
                QMI_LOC_BATCHED_REPORT_MASK_VALID_TIMESTAMP_UTC_V02) {
                temp.timestamp = ind.batchedReportList[i].timestampUtc;
            }
            if (ind.batchedReportList[i].validFields &
                QMI_LOC_BATCHED_REPORT_MASK_VALID_HOR_CIR_UNC_V02) {
                temp.accuracy = ind.batchedReportList[i].horUncCircular;
                temp.flags |= LOCATION_HAS_ACCURACY_BIT;
            }
            if (ind.batchedReportList[i].validFields &
                QMI_LOC_BATCHED_REPORT_MASK_VALID_HEADING_V02) {
                temp.bearing = ind.batchedReportList[i].heading;
                temp.flags |= LOCATION_HAS_BEARING_BIT;
            }
            if (ind.batchedReportList[i].validFields &
                QMI_LOC_BATCHED_REPORT_MASK_VALID_SPEED_HOR_V02) {
                temp.speed = ind.batchedReportList[i].speedHorizontal;
                temp.flags |= LOCATION_HAS_SPEED_BIT;
            }
            if (ind.batchedReportList[i].validFields &
                QMI_LOC_BATCHED_REPORT_MASK_VALID_TECH_MASK_V02) {
                if (QMI_LOC_POS_TECH_MASK_SATELLITE_V02 & ind.batchedReportList[i].technologyMask) {
                    temp.techMask |= LOCATION_TECHNOLOGY_GNSS_BIT;
                }
                if (QMI_LOC_POS_TECH_MASK_CELLID_V02 & ind.batchedReportList[i].technologyMask) {
                    temp.techMask |= LOCATION_TECHNOLOGY_CELL_BIT;
                }
                if (QMI_LOC_POS_TECH_MASK_WIFI_V02 & ind.batchedReportList[i].technologyMask) {
                    temp.techMask |= LOCATION_TECHNOLOGY_WIFI_BIT;
                }
                if (QMI_LOC_POS_TECH_MASK_SENSORS_V02 & ind.batchedReportList[i].technologyMask) {
                    temp.techMask |= LOCATION_TECHNOLOGY_SENSORS_BIT;
                }
            }
            if (ind.batchedReportList[i].validFields &
                QMI_LOC_BATCHED_REPORT_MASK_VALID_VERT_UNC_V02) {
                temp.verticalAccuracy = ind.batchedReportList[i].vertUnc;
                temp.flags |= LOCATION_HAS_VERTICAL_ACCURACY_BIT;
            }
            if (ind.batchedReportList[i].validFields &
                QMI_LOC_BATCHED_REPORT_MASK_VALID_SPEED_UNC_V02) {
                temp.speedAccuracy = ind.batchedReportList[i].speedUnc;
                temp.flags |= LOCATION_HAS_SPEED_ACCURACY_BIT;
            }
            if (ind.batchedReportList[i].validFields &
                QMI_LOC_BATCHED_REPORT_MASK_VALID_HEADING_UNC_V02) {
                temp.bearingAccuracy = ind.batchedReportList[i].headingUnc;
                temp.flags |= LOCATION_HAS_BEARING_ACCURACY_BIT;
            }
            pLocationPiece[i] = temp;
        }
        numbOfEntries = ind.numberOfEntries;
        LOC_LOGD("%s] Read out %zu batched locations from modem.",
                 __func__, numbOfEntries);
    } else {
        LOC_LOGD("%s] Modem does not return batched location.", __func__);
    }
}

LocationError LocApiV02::queryAccumulatedTripDistanceSync(uint32_t &accumulatedTripDistance,
        uint32_t &numOfBatchedPositions)
{
    locClientStatusEnumType st = eLOC_CLIENT_SUCCESS;
    locClientReqUnionType req_union;
    locClientStatusEnumType status;

    qmiLocQueryOTBAccumulatedDistanceReqMsgT_v02 accumulated_distance_req;
    qmiLocQueryOTBAccumulatedDistanceIndMsgT_v02 accumulated_distance_ind;

    memset(&accumulated_distance_req,0,sizeof(accumulated_distance_req));
    memset(&accumulated_distance_ind, 0, sizeof(accumulated_distance_ind));

    req_union.pQueryOTBAccumulatedDistanceReq = &accumulated_distance_req;

    status = locSyncSendReq(QMI_LOC_QUERY_OTB_ACCUMULATED_DISTANCE_REQ_V02,
                            req_union,
                            LOC_ENGINE_SYNC_REQUEST_TIMEOUT,
                            QMI_LOC_QUERY_OTB_ACCUMULATED_DISTANCE_IND_V02,
                            &accumulated_distance_ind);
    if ((eLOC_CLIENT_SUCCESS != status) ||
        (eQMI_LOC_SUCCESS_V02 != accumulated_distance_ind.status))
    {
        LOC_LOGE ("%s:%d]: error! status = %d, accumulated_distance_ind.status = %d\n",
                __func__, __LINE__,
                (status),
                (accumulated_distance_ind.status));
        return LOCATION_ERROR_GENERAL_FAILURE;
    }
    else
    {
        LOC_LOGD("Got accumulated distance: %u number of accumulated positions %u",
        accumulated_distance_ind.accumulatedDistance, accumulated_distance_ind.batchedPosition);

        accumulatedTripDistance = accumulated_distance_ind.accumulatedDistance;
        numOfBatchedPositions = accumulated_distance_ind.batchedPosition;

        return LOCATION_ERROR_SUCCESS;
    }
}

void LocApiV02::queryAccumulatedTripDistance(
        LocApiResponseData<LocApiBatchData>* adapterResponseData)
{
    sendMsg(new LocApiMsg([this, adapterResponseData] () {
        LocationError err = LOCATION_ERROR_SUCCESS;
        LocApiBatchData data;
        err = queryAccumulatedTripDistanceSync(data.accumulatedDistance,
                                               data.numOfBatchedPositions);
        if (adapterResponseData != NULL) {
            adapterResponseData->returnToSender(err, data);
        }
    }));
}

void LocApiV02::addToCallQueue(LocApiResponse* adapterResponse)
{
    sendMsg(new LocApiMsg([adapterResponse] () {
        if (adapterResponse != NULL) {
            adapterResponse->returnToSender(LOCATION_ERROR_SUCCESS);
        }
    }));
}

/* convert dgnss constellation mask from QMI loc to loc eng format */
void LocApiV02::convertGnssConestellationMask(
        qmiLocGNSSConstellEnumT_v02 qmiConstellationEnum,
        GnssConstellationTypeMask& constellationMask) {

    constellationMask = 0x0;
    if (qmiConstellationEnum & eQMI_SYSTEM_GPS_V02) {
        constellationMask |= GNSS_CONSTELLATION_TYPE_GPS_BIT;
    }

    if (qmiConstellationEnum & eQMI_SYSTEM_GLO_V02) {
        constellationMask |= GNSS_CONSTELLATION_TYPE_GLONASS_BIT;
    }

    if (qmiConstellationEnum & eQMI_SYSTEM_BDS_V02) {
        constellationMask |= GNSS_CONSTELLATION_TYPE_BEIDOU_BIT;
    }

    if (qmiConstellationEnum & eQMI_SYSTEM_GAL_V02) {
        constellationMask |= GNSS_CONSTELLATION_TYPE_GALILEO_BIT;
    }

    if (qmiConstellationEnum & eQMI_SYSTEM_QZSS_V02) {
        constellationMask |= GNSS_CONSTELLATION_TYPE_QZSS_BIT;
    }

    if (qmiConstellationEnum & eQMI_SYSTEM_NAVIC_V02) {
        constellationMask |= GNSS_CONSTELLATION_TYPE_NAVIC_BIT;
    }
}

GnssSignalTypeMask LocApiV02::convertQmiGnssSignalType(
        qmiLocGnssSignalTypeMaskT_v02 qmiGnssSignalType) {
    GnssSignalTypeMask gnssSignalType = (GnssSignalTypeMask)0;

    switch (qmiGnssSignalType) {
    case QMI_LOC_MASK_GNSS_SIGNAL_TYPE_GPS_L1CA_V02:
        gnssSignalType = GNSS_SIGNAL_GPS_L1CA;
        break;
    case QMI_LOC_MASK_GNSS_SIGNAL_TYPE_GPS_L1C_V02:
        gnssSignalType = GNSS_SIGNAL_GPS_L1C;
        break;
    case QMI_LOC_MASK_GNSS_SIGNAL_TYPE_GPS_L2C_L_V02:
        gnssSignalType = GNSS_SIGNAL_GPS_L2;
        break;
    case QMI_LOC_MASK_GNSS_SIGNAL_TYPE_GPS_L5_Q_V02:
        gnssSignalType = GNSS_SIGNAL_GPS_L5;
        break;
    case QMI_LOC_MASK_GNSS_SIGNAL_TYPE_GLONASS_G1_V02:
        gnssSignalType = GNSS_SIGNAL_GLONASS_G1;
        break;
    case QMI_LOC_MASK_GNSS_SIGNAL_TYPE_GLONASS_G2_V02:
        gnssSignalType = GNSS_SIGNAL_GLONASS_G2;
        break;
    case QMI_LOC_MASK_GNSS_SIGNAL_TYPE_GALILEO_E1_C_V02:
        gnssSignalType = GNSS_SIGNAL_GALILEO_E1;
        break;
    case QMI_LOC_MASK_GNSS_SIGNAL_TYPE_GALILEO_E5A_Q_V02:
        gnssSignalType = GNSS_SIGNAL_GALILEO_E5A;
        break;
    case QMI_LOC_MASK_GNSS_SIGNAL_TYPE_GALILEO_E5B_Q_V02:
        gnssSignalType = GNSS_SIGNAL_GALILEO_E5B;
        break;
    case QMI_LOC_MASK_GNSS_SIGNAL_TYPE_BEIDOU_B1_I_V02:
        gnssSignalType = GNSS_SIGNAL_BEIDOU_B1I;
        break;
    case QMI_LOC_MASK_GNSS_SIGNAL_TYPE_BEIDOU_B1C_V02:
        gnssSignalType = GNSS_SIGNAL_BEIDOU_B1C;
        break;
    case QMI_LOC_MASK_GNSS_SIGNAL_TYPE_BEIDOU_B2_I_V02:
        gnssSignalType = GNSS_SIGNAL_BEIDOU_B2I;
        break;
    case QMI_LOC_MASK_GNSS_SIGNAL_TYPE_BEIDOU_B2A_I_V02:
        gnssSignalType = GNSS_SIGNAL_BEIDOU_B2AI;
        break;
    case QMI_LOC_MASK_GNSS_SIGNAL_TYPE_QZSS_L1CA_V02:
        gnssSignalType = GNSS_SIGNAL_QZSS_L1CA;
        break;
    case QMI_LOC_MASK_GNSS_SIGNAL_TYPE_QZSS_L1S_V02:
        gnssSignalType =  GNSS_SIGNAL_QZSS_L1S;
        break;
    case QMI_LOC_MASK_GNSS_SIGNAL_TYPE_QZSS_L2C_L_V02:
        gnssSignalType = GNSS_SIGNAL_QZSS_L2;
        break;
    case QMI_LOC_MASK_GNSS_SIGNAL_TYPE_QZSS_L5_Q_V02:
        gnssSignalType = GNSS_SIGNAL_QZSS_L5;
        break;
    case QMI_LOC_MASK_GNSS_SIGNAL_TYPE_SBAS_L1_CA_V02:
        gnssSignalType = GNSS_SIGNAL_SBAS_L1;
        break;
    case QMI_LOC_MASK_GNSS_SIGNAL_TYPE_NAVIC_L5_V02:
        gnssSignalType = GNSS_SIGNAL_NAVIC_L5;
        break;
    case QMI_LOC_MASK_GNSS_SIGNAL_TYPE_BEIDOU_B2A_Q_V02:
        gnssSignalType = GNSS_SIGNAL_BEIDOU_B2AQ;
        break;
    default:
        break;
    }

    return gnssSignalType;
}
