Home | History | Annotate | Download | only in gnss
      1 /* Copyright (c) 2017, The Linux Foundation. All rights reserved.
      2  *
      3  * Redistribution and use in source and binary forms, with or without
      4  * modification, are permitted provided that the following conditions are
      5  * met:
      6  *     * Redistributions of source code must retain the above copyright
      7  *       notice, this list of conditions and the following disclaimer.
      8  *     * Redistributions in binary form must reproduce the above
      9  *       copyright notice, this list of conditions and the following
     10  *       disclaimer in the documentation and/or other materials provided
     11  *       with the distribution.
     12  *     * Neither the name of The Linux Foundation, nor the names of its
     13  *       contributors may be used to endorse or promote products derived
     14  *       from this software without specific prior written permission.
     15  *
     16  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
     17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
     19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
     20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
     23  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     24  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
     25  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
     26  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27  *
     28  */
     29 #define LOG_TAG "LocSvc_GnssAdapter"
     30 
     31 #include <inttypes.h>
     32 #include <sys/stat.h>
     33 #include <errno.h>
     34 #include <ctype.h>
     35 #include <cutils/properties.h>
     36 #include <math.h>
     37 #include <arpa/inet.h>
     38 #include <netinet/in.h>
     39 #include <netdb.h>
     40 #include <GnssAdapter.h>
     41 #include <string>
     42 #include <loc_log.h>
     43 #include <loc_nmea.h>
     44 #include <Agps.h>
     45 #include <SystemStatus.h>
     46 
     47 #include <loc_nmea.h>
     48 #include <vector>
     49 #include <string>
     50 
     51 using namespace loc_core;
     52 
     53 GnssAdapter::GnssAdapter() :
     54     LocAdapterBase(0,
     55                    LocDualContext::getLocFgContext(NULL,
     56                                                    NULL,
     57                                                    LocDualContext::mLocationHalName,
     58                                                    false)),
     59     mUlpProxy(new UlpProxyBase()),
     60     mUlpPositionMode(),
     61     mGnssSvIdUsedInPosition(),
     62     mGnssSvIdUsedInPosAvail(false),
     63     mControlCallbacks(),
     64     mPowerVoteId(0),
     65     mNmeaMask(0),
     66     mNiData(),
     67     mAgpsManager(),
     68     mAgpsCbInfo(),
     69     mSystemStatus(SystemStatus::getInstance(mMsgTask)),
     70     mXtraObserver(mSystemStatus->getOsObserver(), mMsgTask)
     71 {
     72     LOC_LOGD("%s]: Constructor %p", __func__, this);
     73     mUlpPositionMode.mode = LOC_POSITION_MODE_INVALID;
     74     readConfigCommand();
     75     setConfigCommand();
     76 }
     77 
     78 void
     79 GnssAdapter::setControlCallbacksCommand(LocationControlCallbacks& controlCallbacks)
     80 {
     81     struct MsgSetControlCallbacks : public LocMsg {
     82         GnssAdapter& mAdapter;
     83         const LocationControlCallbacks mControlCallbacks;
     84         inline MsgSetControlCallbacks(GnssAdapter& adapter,
     85                                       LocationControlCallbacks& controlCallbacks) :
     86             LocMsg(),
     87             mAdapter(adapter),
     88             mControlCallbacks(controlCallbacks) {}
     89         inline virtual void proc() const {
     90             mAdapter.setControlCallbacks(mControlCallbacks);
     91         }
     92     };
     93 
     94     sendMsg(new MsgSetControlCallbacks(*this, controlCallbacks));
     95 }
     96 
     97 void
     98 GnssAdapter::convertOptions(LocPosMode& out, const LocationOptions& options)
     99 {
    100     LocPosMode locPosMode = {};
    101     switch (options.mode) {
    102     case GNSS_SUPL_MODE_MSB:
    103         out.mode = LOC_POSITION_MODE_MS_BASED;
    104         break;
    105     case GNSS_SUPL_MODE_MSA:
    106         out.mode = LOC_POSITION_MODE_MS_ASSISTED;
    107         break;
    108     default:
    109         out.mode = LOC_POSITION_MODE_STANDALONE;
    110         break;
    111     }
    112     out.share_position = true;
    113     out.min_interval = options.minInterval;
    114 }
    115 
    116 void
    117 GnssAdapter::convertLocation(Location& out, const LocGpsLocation& locGpsLocation,
    118                              const GpsLocationExtended& locationExtended,
    119                              const LocPosTechMask techMask)
    120 {
    121     memset(&out, 0, sizeof(Location));
    122     out.size = sizeof(Location);
    123     if (LOC_GPS_LOCATION_HAS_LAT_LONG & locGpsLocation.flags) {
    124         out.flags |= LOCATION_HAS_LAT_LONG_BIT;
    125         out.latitude = locGpsLocation.latitude;
    126         out.longitude = locGpsLocation.longitude;
    127     }
    128     if (LOC_GPS_LOCATION_HAS_ALTITUDE & locGpsLocation.flags) {
    129         out.flags |= LOCATION_HAS_ALTITUDE_BIT;
    130         out.altitude = locGpsLocation.altitude;
    131     }
    132     if (LOC_GPS_LOCATION_HAS_SPEED & locGpsLocation.flags) {
    133         out.flags |= LOCATION_HAS_SPEED_BIT;
    134         out.speed = locGpsLocation.speed;
    135     }
    136     if (LOC_GPS_LOCATION_HAS_BEARING & locGpsLocation.flags) {
    137         out.flags |= LOCATION_HAS_BEARING_BIT;
    138         out.bearing = locGpsLocation.bearing;
    139     }
    140     if (LOC_GPS_LOCATION_HAS_ACCURACY & locGpsLocation.flags) {
    141         out.flags |= LOCATION_HAS_ACCURACY_BIT;
    142         out.accuracy = locGpsLocation.accuracy;
    143     }
    144     if (GPS_LOCATION_EXTENDED_HAS_VERT_UNC & locationExtended.flags) {
    145         out.flags |= LOCATION_HAS_VERTICAL_ACCURACY_BIT;
    146         out.verticalAccuracy = locationExtended.vert_unc;
    147     }
    148     if (GPS_LOCATION_EXTENDED_HAS_SPEED_UNC & locationExtended.flags) {
    149         out.flags |= LOCATION_HAS_SPEED_ACCURACY_BIT;
    150         out.speedAccuracy = locationExtended.speed_unc;
    151     }
    152     if (GPS_LOCATION_EXTENDED_HAS_BEARING_UNC & locationExtended.flags) {
    153         out.flags |= LOCATION_HAS_BEARING_ACCURACY_BIT;
    154         out.bearingAccuracy = locationExtended.bearing_unc;
    155     }
    156     out.timestamp = locGpsLocation.timestamp;
    157     if (LOC_POS_TECH_MASK_SATELLITE & techMask) {
    158         out.techMask |= LOCATION_TECHNOLOGY_GNSS_BIT;
    159     }
    160     if (LOC_POS_TECH_MASK_CELLID & techMask) {
    161         out.techMask |= LOCATION_TECHNOLOGY_CELL_BIT;
    162     }
    163     if (LOC_POS_TECH_MASK_WIFI & techMask) {
    164         out.techMask |= LOCATION_TECHNOLOGY_WIFI_BIT;
    165     }
    166     if (LOC_POS_TECH_MASK_SENSORS & techMask) {
    167         out.techMask |= LOCATION_TECHNOLOGY_SENSORS_BIT;
    168     }
    169 }
    170 
    171 void
    172 GnssAdapter::convertLocationInfo(GnssLocationInfoNotification& out,
    173                                  const GpsLocationExtended& locationExtended)
    174 {
    175     out.size = sizeof(GnssLocationInfoNotification);
    176     if (GPS_LOCATION_EXTENDED_HAS_ALTITUDE_MEAN_SEA_LEVEL & locationExtended.flags) {
    177         out.flags |= GNSS_LOCATION_INFO_ALTITUDE_MEAN_SEA_LEVEL_BIT;
    178         out.altitudeMeanSeaLevel = locationExtended.altitudeMeanSeaLevel;
    179     }
    180     if (GPS_LOCATION_EXTENDED_HAS_DOP & locationExtended.flags) {
    181         out.flags |= GNSS_LOCATION_INFO_DOP_BIT;
    182         out.pdop = locationExtended.pdop;
    183         out.hdop = locationExtended.hdop;
    184         out.vdop = locationExtended.vdop;
    185     }
    186     if (GPS_LOCATION_EXTENDED_HAS_MAG_DEV & locationExtended.flags) {
    187         out.flags |= GNSS_LOCATION_INFO_MAGNETIC_DEVIATION_BIT;
    188         out.magneticDeviation = locationExtended.magneticDeviation;
    189     }
    190     if (GPS_LOCATION_EXTENDED_HAS_HOR_RELIABILITY & locationExtended.flags) {
    191         out.flags |= GNSS_LOCATION_INFO_HOR_RELIABILITY_BIT;
    192         switch (locationExtended.horizontal_reliability) {
    193             case LOC_RELIABILITY_VERY_LOW:
    194                 out.horReliability = LOCATION_RELIABILITY_VERY_LOW;
    195                 break;
    196             case LOC_RELIABILITY_LOW:
    197                 out.horReliability = LOCATION_RELIABILITY_LOW;
    198                 break;
    199             case LOC_RELIABILITY_MEDIUM:
    200                 out.horReliability = LOCATION_RELIABILITY_MEDIUM;
    201                 break;
    202             case LOC_RELIABILITY_HIGH:
    203                 out.horReliability = LOCATION_RELIABILITY_HIGH;
    204                 break;
    205             default:
    206                 out.horReliability = LOCATION_RELIABILITY_NOT_SET;
    207                 break;
    208         }
    209     }
    210     if (GPS_LOCATION_EXTENDED_HAS_VERT_RELIABILITY & locationExtended.flags) {
    211         out.flags |= GNSS_LOCATION_INFO_VER_RELIABILITY_BIT;
    212         switch (locationExtended.vertical_reliability) {
    213             case LOC_RELIABILITY_VERY_LOW:
    214                 out.verReliability = LOCATION_RELIABILITY_VERY_LOW;
    215                 break;
    216             case LOC_RELIABILITY_LOW:
    217                 out.verReliability = LOCATION_RELIABILITY_LOW;
    218                 break;
    219             case LOC_RELIABILITY_MEDIUM:
    220                 out.verReliability = LOCATION_RELIABILITY_MEDIUM;
    221                 break;
    222             case LOC_RELIABILITY_HIGH:
    223                 out.verReliability = LOCATION_RELIABILITY_HIGH;
    224                 break;
    225             default:
    226                 out.verReliability = LOCATION_RELIABILITY_NOT_SET;
    227                 break;
    228         }
    229     }
    230     if (GPS_LOCATION_EXTENDED_HAS_HOR_ELIP_UNC_MAJOR & locationExtended.flags) {
    231         out.flags |= GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_SEMI_MAJOR_BIT;
    232         out.horUncEllipseSemiMajor = locationExtended.horUncEllipseSemiMajor;
    233     }
    234     if (GPS_LOCATION_EXTENDED_HAS_HOR_ELIP_UNC_MINOR & locationExtended.flags) {
    235         out.flags |= GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_SEMI_MINOR_BIT;
    236         out.horUncEllipseSemiMinor = locationExtended.horUncEllipseSemiMinor;
    237     }
    238     if (GPS_LOCATION_EXTENDED_HAS_HOR_ELIP_UNC_AZIMUTH & locationExtended.flags) {
    239         out.flags |= GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_AZIMUTH_BIT;
    240         out.horUncEllipseOrientAzimuth = locationExtended.horUncEllipseOrientAzimuth;
    241     }
    242 }
    243 
    244 inline uint32_t
    245 GnssAdapter::convertGpsLock(const GnssConfigGpsLock gpsLock)
    246 {
    247     switch (gpsLock) {
    248         case GNSS_CONFIG_GPS_LOCK_MO:
    249             return 1;
    250         case GNSS_CONFIG_GPS_LOCK_NI:
    251             return 2;
    252         case GNSS_CONFIG_GPS_LOCK_MO_AND_NI:
    253             return 3;
    254         case GNSS_CONFIG_GPS_LOCK_NONE:
    255         default:
    256             return 0;
    257     }
    258 }
    259 
    260 inline GnssConfigGpsLock
    261 GnssAdapter::convertGpsLock(const uint32_t gpsLock)
    262 {
    263     switch (gpsLock) {
    264         case 1:
    265             return GNSS_CONFIG_GPS_LOCK_MO;
    266         case 2:
    267             return GNSS_CONFIG_GPS_LOCK_NI;
    268         case 3:
    269             return GNSS_CONFIG_GPS_LOCK_MO_AND_NI;
    270         case 0:
    271         default:
    272             return GNSS_CONFIG_GPS_LOCK_NONE;
    273     }
    274 }
    275 
    276 inline uint32_t
    277 GnssAdapter::convertSuplVersion(const GnssConfigSuplVersion suplVersion)
    278 {
    279     switch (suplVersion) {
    280         case GNSS_CONFIG_SUPL_VERSION_2_0_0:
    281             return 0x00020000;
    282         case GNSS_CONFIG_SUPL_VERSION_2_0_2:
    283             return 0x00020002;
    284         case GNSS_CONFIG_SUPL_VERSION_1_0_0:
    285         default:
    286             return 0x00010000;
    287     }
    288 }
    289 
    290 inline GnssConfigSuplVersion
    291 GnssAdapter::convertSuplVersion(const uint32_t suplVersion)
    292 {
    293     switch (suplVersion) {
    294         case 0x00020000:
    295             return GNSS_CONFIG_SUPL_VERSION_2_0_0;
    296         case 0x00020002:
    297             return GNSS_CONFIG_SUPL_VERSION_2_0_2;
    298         case 0x00010000:
    299         default:
    300             return GNSS_CONFIG_SUPL_VERSION_1_0_0;
    301     }
    302 }
    303 
    304 inline uint32_t
    305 GnssAdapter::convertLppProfile(const GnssConfigLppProfile lppProfile)
    306 {
    307     switch (lppProfile) {
    308         case GNSS_CONFIG_LPP_PROFILE_USER_PLANE:
    309             return 1;
    310         case GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE:
    311             return 2;
    312         case GNSS_CONFIG_LPP_PROFILE_USER_PLANE_AND_CONTROL_PLANE:
    313             return 3;
    314         case GNSS_CONFIG_LPP_PROFILE_RRLP_ON_LTE:
    315         default:
    316             return 0;
    317     }
    318 }
    319 
    320 inline GnssConfigLppProfile
    321 GnssAdapter::convertLppProfile(const uint32_t lppProfile)
    322 {
    323     switch (lppProfile) {
    324         case 1:
    325             return GNSS_CONFIG_LPP_PROFILE_USER_PLANE;
    326         case 2:
    327             return GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE;
    328         case 3:
    329             return GNSS_CONFIG_LPP_PROFILE_USER_PLANE_AND_CONTROL_PLANE;
    330         case 0:
    331         default:
    332             return GNSS_CONFIG_LPP_PROFILE_RRLP_ON_LTE;
    333     }
    334 }
    335 
    336 uint32_t
    337 GnssAdapter::convertLppeCp(const GnssConfigLppeControlPlaneMask lppeControlPlaneMask)
    338 {
    339     uint32_t mask = 0;
    340     if (GNSS_CONFIG_LPPE_CONTROL_PLANE_DBH_BIT & lppeControlPlaneMask) {
    341         mask |= (1<<0);
    342     }
    343     if (GNSS_CONFIG_LPPE_CONTROL_PLANE_WLAN_AP_MEASUREMENTS_BIT & lppeControlPlaneMask) {
    344         mask |= (1<<1);
    345     }
    346     if (GNSS_CONFIG_LPPE_CONTROL_PLANE_SRN_AP_MEASUREMENTS_BIT & lppeControlPlaneMask) {
    347         mask |= (1<<2);
    348     }
    349     if (GNSS_CONFIG_LPPE_CONTROL_PLANE_SENSOR_BARO_MEASUREMENTS_BIT & lppeControlPlaneMask) {
    350         mask |= (1<<3);
    351     }
    352     return mask;
    353 }
    354 
    355 GnssConfigLppeControlPlaneMask
    356 GnssAdapter::convertLppeCp(const uint32_t lppeControlPlaneMask)
    357 {
    358     GnssConfigLppeControlPlaneMask mask = 0;
    359     if ((1<<0) & lppeControlPlaneMask) {
    360         mask |= GNSS_CONFIG_LPPE_CONTROL_PLANE_DBH_BIT;
    361     }
    362     if ((1<<1) & lppeControlPlaneMask) {
    363         mask |= GNSS_CONFIG_LPPE_CONTROL_PLANE_WLAN_AP_MEASUREMENTS_BIT;
    364     }
    365     if ((1<<2) & lppeControlPlaneMask) {
    366         mask |= GNSS_CONFIG_LPPE_CONTROL_PLANE_SRN_AP_MEASUREMENTS_BIT;
    367     }
    368     if ((1<<3) & lppeControlPlaneMask) {
    369         mask |= GNSS_CONFIG_LPPE_CONTROL_PLANE_SENSOR_BARO_MEASUREMENTS_BIT;
    370     }
    371     return mask;
    372 }
    373 
    374 
    375 uint32_t
    376 GnssAdapter::convertLppeUp(const GnssConfigLppeUserPlaneMask lppeUserPlaneMask)
    377 {
    378     uint32_t mask = 0;
    379     if (GNSS_CONFIG_LPPE_USER_PLANE_DBH_BIT & lppeUserPlaneMask) {
    380         mask |= (1<<0);
    381     }
    382     if (GNSS_CONFIG_LPPE_USER_PLANE_WLAN_AP_MEASUREMENTS_BIT & lppeUserPlaneMask) {
    383         mask |= (1<<1);
    384     }
    385     if (GNSS_CONFIG_LPPE_USER_PLANE_SRN_AP_MEASUREMENTS_BIT & lppeUserPlaneMask) {
    386         mask |= (1<<2);
    387     }
    388     if (GNSS_CONFIG_LPPE_USER_PLANE_SENSOR_BARO_MEASUREMENTS_BIT & lppeUserPlaneMask) {
    389         mask |= (1<<3);
    390     }
    391     return mask;
    392 }
    393 
    394 GnssConfigLppeUserPlaneMask
    395 GnssAdapter::convertLppeUp(const uint32_t lppeUserPlaneMask)
    396 {
    397     GnssConfigLppeUserPlaneMask mask = 0;
    398     if ((1<<0) & lppeUserPlaneMask) {
    399         mask |= GNSS_CONFIG_LPPE_USER_PLANE_DBH_BIT;
    400     }
    401     if ((1<<1) & lppeUserPlaneMask) {
    402         mask |= GNSS_CONFIG_LPPE_USER_PLANE_WLAN_AP_MEASUREMENTS_BIT;
    403     }
    404     if ((1<<2) & lppeUserPlaneMask) {
    405         mask |= GNSS_CONFIG_LPPE_USER_PLANE_SRN_AP_MEASUREMENTS_BIT;
    406     }
    407     if ((1<<3) & lppeUserPlaneMask) {
    408         mask |= GNSS_CONFIG_LPPE_USER_PLANE_SENSOR_BARO_MEASUREMENTS_BIT;
    409     }
    410     return mask;
    411 }
    412 
    413 uint32_t
    414 GnssAdapter::convertAGloProt(const GnssConfigAGlonassPositionProtocolMask aGloPositionProtocolMask)
    415 {
    416     uint32_t mask = 0;
    417     if (GNSS_CONFIG_RRC_CONTROL_PLANE_BIT & aGloPositionProtocolMask) {
    418         mask |= (1<<0);
    419     }
    420     if (GNSS_CONFIG_RRLP_USER_PLANE_BIT & aGloPositionProtocolMask) {
    421         mask |= (1<<1);
    422     }
    423     if (GNSS_CONFIG_LLP_USER_PLANE_BIT & aGloPositionProtocolMask) {
    424         mask |= (1<<2);
    425     }
    426     if (GNSS_CONFIG_LLP_CONTROL_PLANE_BIT & aGloPositionProtocolMask) {
    427         mask |= (1<<3);
    428     }
    429     return mask;
    430 }
    431 
    432 uint32_t
    433 GnssAdapter::convertEP4ES(const GnssConfigEmergencyPdnForEmergencySupl emergencyPdnForEmergencySupl)
    434 {
    435     switch (emergencyPdnForEmergencySupl) {
    436        case GNSS_CONFIG_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_YES:
    437            return 1;
    438        case GNSS_CONFIG_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_NO:
    439        default:
    440            return 0;
    441     }
    442 }
    443 
    444 uint32_t
    445 GnssAdapter::convertSuplEs(const GnssConfigSuplEmergencyServices suplEmergencyServices)
    446 {
    447     switch (suplEmergencyServices) {
    448        case GNSS_CONFIG_SUPL_EMERGENCY_SERVICES_YES:
    449            return 1;
    450        case GNSS_CONFIG_SUPL_EMERGENCY_SERVICES_NO:
    451        default:
    452            return 0;
    453     }
    454 }
    455 
    456 uint32_t
    457 GnssAdapter::convertSuplMode(const GnssConfigSuplModeMask suplModeMask)
    458 {
    459     uint32_t mask = 0;
    460     if (GNSS_CONFIG_SUPL_MODE_MSB_BIT & suplModeMask) {
    461         mask |= (1<<0);
    462     }
    463     if (GNSS_CONFIG_SUPL_MODE_MSA_BIT & suplModeMask) {
    464         mask |= (1<<1);
    465     }
    466     return mask;
    467 }
    468 
    469 bool
    470 GnssAdapter::resolveInAddress(const char* hostAddress, struct in_addr* inAddress)
    471 {
    472     bool ret = true;
    473 
    474     struct hostent* hp;
    475     hp = gethostbyname(hostAddress);
    476     if (hp != NULL) { /* DNS OK */
    477         memcpy(inAddress, hp->h_addr_list[0], hp->h_length);
    478     } else {
    479         /* Try IP representation */
    480         if (inet_aton(hostAddress, inAddress) == 0) {
    481             /* IP not valid */
    482             LOC_LOGE("%s]: DNS query on '%s' failed", __func__, hostAddress);
    483             ret = false;
    484         }
    485     }
    486 
    487     return ret;
    488 }
    489 
    490 void
    491 GnssAdapter::readConfigCommand()
    492 {
    493     LOC_LOGD("%s]: ", __func__);
    494 
    495     struct MsgReadConfig : public LocMsg {
    496         GnssAdapter* mAdapter;
    497         ContextBase& mContext;
    498         inline MsgReadConfig(GnssAdapter* adapter,
    499                              ContextBase& context) :
    500             LocMsg(),
    501             mAdapter(adapter),
    502             mContext(context) {}
    503         inline virtual void proc() const {
    504             // reads config into mContext->mGps_conf
    505             mContext.readConfig();
    506             mContext.requestUlp((LocAdapterBase*)mAdapter, mContext.getCarrierCapabilities());
    507         }
    508     };
    509 
    510     if (mContext != NULL) {
    511         sendMsg(new MsgReadConfig(this, *mContext));
    512     }
    513 }
    514 
    515 void
    516 GnssAdapter::setConfigCommand()
    517 {
    518     LOC_LOGD("%s]: ", __func__);
    519 
    520     struct MsgSetConfig : public LocMsg {
    521         GnssAdapter& mAdapter;
    522         LocApiBase& mApi;
    523         inline MsgSetConfig(GnssAdapter& adapter,
    524                             LocApiBase& api) :
    525             LocMsg(),
    526             mAdapter(adapter),
    527             mApi(api) {}
    528         inline virtual void proc() const {
    529             if (ContextBase::mGps_conf.AGPS_CONFIG_INJECT) {
    530                 mApi.setSUPLVersion(mAdapter.convertSuplVersion(ContextBase::mGps_conf.SUPL_VER));
    531                 mApi.setLPPConfig(mAdapter.convertLppProfile(ContextBase::mGps_conf.LPP_PROFILE));
    532                 mApi.setAGLONASSProtocol(ContextBase::mGps_conf.A_GLONASS_POS_PROTOCOL_SELECT);
    533             }
    534             mApi.setSensorControlConfig(ContextBase::mSap_conf.SENSOR_USAGE,
    535                                         ContextBase::mSap_conf.SENSOR_PROVIDER);
    536             mApi.setLPPeProtocolCp(
    537                 mAdapter.convertLppeCp(ContextBase::mGps_conf.LPPE_CP_TECHNOLOGY));
    538             mApi.setLPPeProtocolUp(
    539                 mAdapter.convertLppeUp(ContextBase::mGps_conf.LPPE_UP_TECHNOLOGY));
    540 
    541             // set nmea mask type
    542             uint32_t mask = 0;
    543             if (NMEA_PROVIDER_MP == ContextBase::mGps_conf.NMEA_PROVIDER) {
    544                 mask |= LOC_NMEA_ALL_GENERAL_SUPPORTED_MASK;
    545             }
    546             if (mApi.isFeatureSupported(LOC_SUPPORTED_FEATURE_DEBUG_NMEA_V02)) {
    547                 mask |= LOC_NMEA_MASK_DEBUG_V02;
    548             }
    549             if (mask != 0) {
    550                 mApi.setNMEATypes(mask);
    551             }
    552             mAdapter.mNmeaMask= mask;
    553 
    554             mApi.setXtraVersionCheck(ContextBase::mGps_conf.XTRA_VERSION_CHECK);
    555             if (ContextBase::mSap_conf.GYRO_BIAS_RANDOM_WALK_VALID ||
    556                 ContextBase::mSap_conf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY_VALID ||
    557                 ContextBase::mSap_conf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY_VALID ||
    558                 ContextBase::mSap_conf.RATE_RANDOM_WALK_SPECTRAL_DENSITY_VALID ||
    559                 ContextBase::mSap_conf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY_VALID ) {
    560                 mApi.setSensorProperties(
    561                     ContextBase::mSap_conf.GYRO_BIAS_RANDOM_WALK_VALID,
    562                     ContextBase::mSap_conf.GYRO_BIAS_RANDOM_WALK,
    563                     ContextBase::mSap_conf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY_VALID,
    564                     ContextBase::mSap_conf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY,
    565                     ContextBase::mSap_conf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY_VALID,
    566                     ContextBase::mSap_conf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY,
    567                     ContextBase::mSap_conf.RATE_RANDOM_WALK_SPECTRAL_DENSITY_VALID,
    568                     ContextBase::mSap_conf.RATE_RANDOM_WALK_SPECTRAL_DENSITY,
    569                     ContextBase::mSap_conf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY_VALID,
    570                     ContextBase::mSap_conf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY);
    571             }
    572             mApi.setSensorPerfControlConfig(
    573                 ContextBase::mSap_conf.SENSOR_CONTROL_MODE,
    574                    ContextBase::mSap_conf.SENSOR_ACCEL_SAMPLES_PER_BATCH,
    575                    ContextBase::mSap_conf.SENSOR_ACCEL_BATCHES_PER_SEC,
    576                    ContextBase::mSap_conf.SENSOR_GYRO_SAMPLES_PER_BATCH,
    577                    ContextBase::mSap_conf.SENSOR_GYRO_BATCHES_PER_SEC,
    578                    ContextBase::mSap_conf.SENSOR_ACCEL_SAMPLES_PER_BATCH_HIGH,
    579                    ContextBase::mSap_conf.SENSOR_ACCEL_BATCHES_PER_SEC_HIGH,
    580                    ContextBase::mSap_conf.SENSOR_GYRO_SAMPLES_PER_BATCH_HIGH,
    581                    ContextBase::mSap_conf.SENSOR_GYRO_BATCHES_PER_SEC_HIGH,
    582                    ContextBase::mSap_conf.SENSOR_ALGORITHM_CONFIG_MASK);
    583         }
    584     };
    585 
    586     sendMsg(new MsgSetConfig(*this, *mLocApi));
    587 }
    588 
    589 uint32_t*
    590 GnssAdapter::gnssUpdateConfigCommand(GnssConfig config)
    591 {
    592     // count the number of bits set
    593     GnssConfigFlagsMask flagsCopy = config.flags;
    594     size_t count = 0;
    595     while (flagsCopy > 0) {
    596         if (flagsCopy & 1) {
    597             count++;
    598         }
    599         flagsCopy >>= 1;
    600     }
    601     std::string idsString = "[";
    602     uint32_t* ids = NULL;
    603     if (count > 0) {
    604         ids = new uint32_t[count];
    605         if (ids == nullptr) {
    606             LOC_LOGE("%s] new allocation failed, fatal error.", __func__);
    607             return nullptr;
    608         }
    609         for (size_t i=0; i < count; ++i) {
    610             ids[i] = generateSessionId();
    611             IF_LOC_LOGD {
    612                 idsString += std::to_string(ids[i]) + " ";
    613             }
    614         }
    615     }
    616     idsString += "]";
    617 
    618     LOC_LOGD("%s]: ids %s flags 0x%X", __func__, idsString.c_str(), config.flags);
    619 
    620     struct MsgGnssUpdateConfig : public LocMsg {
    621         GnssAdapter& mAdapter;
    622         LocApiBase& mApi;
    623         GnssConfig mConfig;
    624         uint32_t* mIds;
    625         size_t mCount;
    626         inline MsgGnssUpdateConfig(GnssAdapter& adapter,
    627                                    LocApiBase& api,
    628                                    GnssConfig config,
    629                                    uint32_t* ids,
    630                                    size_t count) :
    631             LocMsg(),
    632             mAdapter(adapter),
    633             mApi(api),
    634             mConfig(config),
    635             mIds(ids),
    636             mCount(count) {}
    637         inline virtual ~MsgGnssUpdateConfig()
    638         {
    639             delete[] mIds;
    640         }
    641         inline virtual void proc() const {
    642             //const size_t MAX_BITS_COUNT = 10;
    643             //LocationError errs[MAX_BITS_COUNT] = {};
    644             LocationError* errs = new LocationError[mCount];
    645             LocationError err = LOCATION_ERROR_SUCCESS;
    646             uint32_t index = 0;
    647 
    648             if (errs == nullptr) {
    649                 LOC_LOGE("%s] new allocation failed, fatal error.", __func__);
    650                 return;
    651             }
    652 
    653             if (mConfig.flags & GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT) {
    654                 uint32_t newGpsLock = mAdapter.convertGpsLock(mConfig.gpsLock);
    655                 ContextBase::mGps_conf.GPS_LOCK = newGpsLock;
    656                 if (0 == mAdapter.getPowerVoteId()) {
    657                     err = mApi.setGpsLock(mConfig.gpsLock);
    658                 }
    659                 if (index < mCount) {
    660                     errs[index++] = err;
    661                 }
    662             }
    663             if (mConfig.flags & GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT) {
    664                 uint32_t newSuplVersion = mAdapter.convertSuplVersion(mConfig.suplVersion);
    665                 if (newSuplVersion != ContextBase::mGps_conf.SUPL_VER &&
    666                     ContextBase::mGps_conf.AGPS_CONFIG_INJECT) {
    667                     ContextBase::mGps_conf.SUPL_VER = newSuplVersion;
    668                     err = mApi.setSUPLVersion(mConfig.suplVersion);
    669                 } else {
    670                     err = LOCATION_ERROR_SUCCESS;
    671                 }
    672                 if (index < mCount) {
    673                     errs[index++] = err;
    674                 }
    675             }
    676             if (mConfig.flags & GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT) {
    677                 if (GNSS_ASSISTANCE_TYPE_SUPL == mConfig.assistanceServer.type) {
    678                     if (ContextBase::mGps_conf.AGPS_CONFIG_INJECT) {
    679                         char serverUrl[MAX_URL_LEN] = {};
    680                         uint32_t length = 0;
    681                         const char noHost[] = "NONE";
    682                         if (NULL == mConfig.assistanceServer.hostName ||
    683                             strncasecmp(noHost,
    684                                         mConfig.assistanceServer.hostName,
    685                                         sizeof(noHost)) == 0) {
    686                         } else {
    687                             length = snprintf(serverUrl, sizeof(serverUrl), "%s:%u",
    688                                               mConfig.assistanceServer.hostName,
    689                                               mConfig.assistanceServer.port);
    690                         }
    691 
    692                         if (sizeof(serverUrl) > length) {
    693                             err = mApi.setServer(serverUrl, length);
    694                         } else {
    695                             err = LOCATION_ERROR_INVALID_PARAMETER;
    696                         }
    697                     } else {
    698                         err = LOCATION_ERROR_SUCCESS;
    699                     }
    700                 } else if (GNSS_ASSISTANCE_TYPE_C2K == mConfig.assistanceServer.type) {
    701                     if (ContextBase::mGps_conf.AGPS_CONFIG_INJECT) {
    702                         struct in_addr addr;
    703                         if (!mAdapter.resolveInAddress(mConfig.assistanceServer.hostName, &addr)) {
    704                             LOC_LOGE("%s]: hostName %s cannot be resolved",
    705                                      __func__, mConfig.assistanceServer.hostName);
    706                             err = LOCATION_ERROR_INVALID_PARAMETER;
    707                         } else {
    708                             unsigned int ip = htonl(addr.s_addr);
    709                             err = mApi.setServer(ip, mConfig.assistanceServer.port,
    710                                                     LOC_AGPS_CDMA_PDE_SERVER);
    711                         }
    712                     } else {
    713                         err = LOCATION_ERROR_SUCCESS;
    714                     }
    715                 } else {
    716                     LOC_LOGE("%s]: Not a valid gnss assistance type %u",
    717                              __func__, mConfig.assistanceServer.type);
    718                     err = LOCATION_ERROR_INVALID_PARAMETER;
    719                 }
    720                 if (index < mCount) {
    721                     errs[index++] = err;
    722                 }
    723             }
    724             if (mConfig.flags & GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT) {
    725                 uint32_t newLppProfile = mAdapter.convertLppProfile(mConfig.lppProfile);
    726                 if (newLppProfile != ContextBase::mGps_conf.LPP_PROFILE &&
    727                     ContextBase::mGps_conf.AGPS_CONFIG_INJECT) {
    728                     ContextBase::mGps_conf.LPP_PROFILE = newLppProfile;
    729                     err = mApi.setLPPConfig(mConfig.lppProfile);
    730                 } else {
    731                     err = LOCATION_ERROR_SUCCESS;
    732                 }
    733                 if (index < mCount) {
    734                     errs[index++] = err;
    735                 }
    736             }
    737             if (mConfig.flags & GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT) {
    738                 uint32_t newLppeControlPlaneMask =
    739                     mAdapter.convertLppeCp(mConfig.lppeControlPlaneMask);
    740                 if (newLppeControlPlaneMask != ContextBase::mGps_conf.LPPE_CP_TECHNOLOGY) {
    741                     ContextBase::mGps_conf.LPPE_CP_TECHNOLOGY = newLppeControlPlaneMask;
    742                     err = mApi.setLPPeProtocolCp(mConfig.lppeControlPlaneMask);
    743                 } else {
    744                     err = LOCATION_ERROR_SUCCESS;
    745                 }
    746                 if (index < mCount) {
    747                     errs[index++] = err;
    748                 }
    749             }
    750             if (mConfig.flags & GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT) {
    751                 uint32_t newLppeUserPlaneMask =
    752                     mAdapter.convertLppeUp(mConfig.lppeUserPlaneMask);
    753                 if (newLppeUserPlaneMask != ContextBase::mGps_conf.LPPE_UP_TECHNOLOGY) {
    754                     ContextBase::mGps_conf.LPPE_UP_TECHNOLOGY = newLppeUserPlaneMask;
    755                     err = mApi.setLPPeProtocolUp(mConfig.lppeUserPlaneMask);
    756                 } else {
    757                     err = LOCATION_ERROR_SUCCESS;
    758                 }
    759                 if (index < mCount) {
    760                     errs[index++] = err;
    761                 }
    762             }
    763             if (mConfig.flags & GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT) {
    764                 uint32_t newAGloProtMask =
    765                     mAdapter.convertAGloProt(mConfig.aGlonassPositionProtocolMask);
    766                 if (newAGloProtMask != ContextBase::mGps_conf.A_GLONASS_POS_PROTOCOL_SELECT &&
    767                     ContextBase::mGps_conf.AGPS_CONFIG_INJECT) {
    768                     ContextBase::mGps_conf.A_GLONASS_POS_PROTOCOL_SELECT = newAGloProtMask;
    769                     err = mApi.setAGLONASSProtocol(mConfig.aGlonassPositionProtocolMask);
    770                 } else {
    771                     err = LOCATION_ERROR_SUCCESS;
    772                 }
    773                 if (index < mCount) {
    774                     errs[index++] = err;
    775                 }
    776             }
    777             if (mConfig.flags & GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT) {
    778                 uint32_t newEP4ES = mAdapter.convertEP4ES(mConfig.emergencyPdnForEmergencySupl);
    779                 if (newEP4ES != ContextBase::mGps_conf.USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL) {
    780                     ContextBase::mGps_conf.USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL = newEP4ES;
    781                 }
    782                 err = LOCATION_ERROR_SUCCESS;
    783                 if (index < mCount) {
    784                     errs[index++] = err;
    785                 }
    786             }
    787             if (mConfig.flags & GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT) {
    788                 uint32_t newSuplEs = mAdapter.convertSuplEs(mConfig.suplEmergencyServices);
    789                 if (newSuplEs != ContextBase::mGps_conf.SUPL_ES) {
    790                     ContextBase::mGps_conf.SUPL_ES = newSuplEs;
    791                 }
    792                 err = LOCATION_ERROR_SUCCESS;
    793                 if (index < mCount) {
    794                     errs[index++] = err;
    795                 }
    796             }
    797             if (mConfig.flags & GNSS_CONFIG_FLAGS_SUPL_MODE_BIT) {
    798                 uint32_t newSuplMode = mAdapter.convertSuplMode(mConfig.suplModeMask);
    799                 if (newSuplMode != ContextBase::mGps_conf.SUPL_MODE) {
    800                     ContextBase::mGps_conf.SUPL_MODE = newSuplMode;
    801                     mAdapter.getUlpProxy()->setCapabilities(
    802                         ContextBase::getCarrierCapabilities());
    803                     mAdapter.broadcastCapabilities(mAdapter.getCapabilities());
    804                 }
    805                 err = LOCATION_ERROR_SUCCESS;
    806                 if (index < mCount) {
    807                     errs[index++] = err;
    808                 }
    809             }
    810 
    811             mAdapter.reportResponse(index, errs, mIds);
    812             delete[] errs;
    813         }
    814     };
    815 
    816     if (NULL != ids) {
    817         sendMsg(new MsgGnssUpdateConfig(*this, *mLocApi, config, ids, count));
    818     } else {
    819         LOC_LOGE("%s]: No GNSS config items to update", __func__);
    820     }
    821 
    822     return ids;
    823 }
    824 
    825 uint32_t
    826 GnssAdapter::gnssDeleteAidingDataCommand(GnssAidingData& data)
    827 {
    828     uint32_t sessionId = generateSessionId();
    829     LOC_LOGD("%s]: id %u", __func__, sessionId);
    830 
    831     struct MsgDeleteAidingData : public LocMsg {
    832         GnssAdapter& mAdapter;
    833         LocApiBase& mApi;
    834         uint32_t mSessionId;
    835         GnssAidingData mData;
    836         inline MsgDeleteAidingData(GnssAdapter& adapter,
    837                                    LocApiBase& api,
    838                                    uint32_t sessionId,
    839                                    GnssAidingData& data) :
    840             LocMsg(),
    841             mAdapter(adapter),
    842             mApi(api),
    843             mSessionId(sessionId),
    844             mData(data) {}
    845         inline virtual void proc() const {
    846             LocationError err = LOCATION_ERROR_SUCCESS;
    847             err = mApi.deleteAidingData(mData);
    848             mAdapter.reportResponse(err, mSessionId);
    849             SystemStatus* s = mAdapter.getSystemStatus();
    850             if ((nullptr != s) && (mData.deleteAll)) {
    851                 s->setDefaultReport();
    852             }
    853         }
    854     };
    855 
    856     sendMsg(new MsgDeleteAidingData(*this, *mLocApi, sessionId, data));
    857     return sessionId;
    858 }
    859 
    860 void
    861 GnssAdapter::injectLocationCommand(double latitude, double longitude, float accuracy)
    862 {
    863     LOC_LOGD("%s]: latitude %8.4f longitude %8.4f accuracy %8.4f",
    864              __func__, latitude, longitude, accuracy);
    865 
    866     struct MsgInjectLocation : public LocMsg {
    867         LocApiBase& mApi;
    868         ContextBase& mContext;
    869         double mLatitude;
    870         double mLongitude;
    871         float mAccuracy;
    872         inline MsgInjectLocation(LocApiBase& api,
    873                                  ContextBase& context,
    874                                  double latitude,
    875                                  double longitude,
    876                                  float accuracy) :
    877             LocMsg(),
    878             mApi(api),
    879             mContext(context),
    880             mLatitude(latitude),
    881             mLongitude(longitude),
    882             mAccuracy(accuracy) {}
    883         inline virtual void proc() const {
    884             if (!mContext.hasCPIExtendedCapabilities()) {
    885                 mApi.injectPosition(mLatitude, mLongitude, mAccuracy);
    886             }
    887         }
    888     };
    889 
    890     sendMsg(new MsgInjectLocation(*mLocApi, *mContext, latitude, longitude, accuracy));
    891 }
    892 
    893 void
    894 GnssAdapter::injectTimeCommand(int64_t time, int64_t timeReference, int32_t uncertainty)
    895 {
    896     LOC_LOGD("%s]: time %lld timeReference %lld uncertainty %d",
    897              __func__, (long long)time, (long long)timeReference, uncertainty);
    898 
    899     struct MsgInjectTime : public LocMsg {
    900         LocApiBase& mApi;
    901         ContextBase& mContext;
    902         int64_t mTime;
    903         int64_t mTimeReference;
    904         int32_t mUncertainty;
    905         inline MsgInjectTime(LocApiBase& api,
    906                              ContextBase& context,
    907                              int64_t time,
    908                              int64_t timeReference,
    909                              int32_t uncertainty) :
    910             LocMsg(),
    911             mApi(api),
    912             mContext(context),
    913             mTime(time),
    914             mTimeReference(timeReference),
    915             mUncertainty(uncertainty) {}
    916         inline virtual void proc() const {
    917             mApi.setTime(mTime, mTimeReference, mUncertainty);
    918         }
    919     };
    920 
    921     sendMsg(new MsgInjectTime(*mLocApi, *mContext, time, timeReference, uncertainty));
    922 }
    923 
    924 void
    925 GnssAdapter::setUlpProxyCommand(UlpProxyBase* ulp)
    926 {
    927     LOC_LOGD("%s]: ", __func__);
    928 
    929     struct MsgSetUlpProxy : public LocMsg {
    930         GnssAdapter& mAdapter;
    931         UlpProxyBase* mUlp;
    932         inline MsgSetUlpProxy(GnssAdapter& adapter,
    933                               UlpProxyBase* ulp) :
    934             LocMsg(),
    935             mAdapter(adapter),
    936             mUlp(ulp) {}
    937         inline virtual void proc() const {
    938             mAdapter.setUlpProxy(mUlp);
    939             if (mUlp) {
    940                 mUlp->setCapabilities(ContextBase::getCarrierCapabilities());
    941             }
    942         }
    943     };
    944 
    945     sendMsg(new MsgSetUlpProxy(*this, ulp));
    946 }
    947 
    948 void
    949 GnssAdapter::setUlpProxy(UlpProxyBase* ulp)
    950 {
    951     if (ulp == mUlpProxy) {
    952         //This takes care of the case when double initalization happens
    953         //and we get the same object back for UlpProxyBase . Do nothing
    954         return;
    955     }
    956 
    957     LOC_LOGV("%s]: %p", __func__, ulp);
    958     if (NULL == ulp) {
    959         LOC_LOGE("%s]: ulp pointer is NULL", __func__);
    960         ulp = new UlpProxyBase();
    961     }
    962 
    963     if (LOC_POSITION_MODE_INVALID != mUlpProxy->mPosMode.mode) {
    964         // need to send this mode and start msg to ULP
    965         ulp->sendFixMode(mUlpProxy->mPosMode);
    966     }
    967 
    968     if (mUlpProxy->mFixSet) {
    969         ulp->sendStartFix();
    970     }
    971 
    972     delete mUlpProxy;
    973     mUlpProxy = ulp;
    974 }
    975 
    976 void
    977 GnssAdapter::addClientCommand(LocationAPI* client, const LocationCallbacks& callbacks)
    978 {
    979     LOC_LOGD("%s]: client %p", __func__, client);
    980 
    981     struct MsgAddClient : public LocMsg {
    982         GnssAdapter& mAdapter;
    983         LocationAPI* mClient;
    984         const LocationCallbacks mCallbacks;
    985         inline MsgAddClient(GnssAdapter& adapter,
    986                             LocationAPI* client,
    987                             const LocationCallbacks& callbacks) :
    988             LocMsg(),
    989             mAdapter(adapter),
    990             mClient(client),
    991             mCallbacks(callbacks) {}
    992         inline virtual void proc() const {
    993             mAdapter.saveClient(mClient, mCallbacks);
    994         }
    995     };
    996 
    997     sendMsg(new MsgAddClient(*this, client, callbacks));
    998 }
    999 
   1000 void
   1001 GnssAdapter::removeClientCommand(LocationAPI* client)
   1002 {
   1003     LOC_LOGD("%s]: client %p", __func__, client);
   1004 
   1005     struct MsgRemoveClient : public LocMsg {
   1006         GnssAdapter& mAdapter;
   1007         LocationAPI* mClient;
   1008         inline MsgRemoveClient(GnssAdapter& adapter,
   1009                                LocationAPI* client) :
   1010             LocMsg(),
   1011             mAdapter(adapter),
   1012             mClient(client) {}
   1013         inline virtual void proc() const {
   1014             mAdapter.stopClientSessions(mClient);
   1015             mAdapter.eraseClient(mClient);
   1016         }
   1017     };
   1018 
   1019     sendMsg(new MsgRemoveClient(*this, client));
   1020 }
   1021 
   1022 void
   1023 GnssAdapter::stopClientSessions(LocationAPI* client)
   1024 {
   1025     LOC_LOGD("%s]: client %p", __func__, client);
   1026     for (auto it = mTrackingSessions.begin(); it != mTrackingSessions.end();) {
   1027         if (client == it->first.client) {
   1028             LocationError err = stopTrackingMultiplex(it->first.client, it->first.id);
   1029             if (LOCATION_ERROR_SUCCESS == err) {
   1030                 it = mTrackingSessions.erase(it);
   1031                 continue;
   1032             }
   1033         }
   1034         ++it; // increment only when not erasing an iterator
   1035     }
   1036 
   1037 }
   1038 
   1039 void
   1040 GnssAdapter::updateClientsEventMask()
   1041 {
   1042     LOC_API_ADAPTER_EVENT_MASK_T mask = 0;
   1043     for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
   1044         if (it->second.trackingCb != nullptr) {
   1045             mask |= LOC_API_ADAPTER_BIT_PARSED_POSITION_REPORT;
   1046         }
   1047         if (it->second.gnssNiCb != nullptr) {
   1048             mask |= LOC_API_ADAPTER_BIT_NI_NOTIFY_VERIFY_REQUEST;
   1049         }
   1050         if (it->second.gnssSvCb != nullptr) {
   1051             mask |= LOC_API_ADAPTER_BIT_SATELLITE_REPORT;
   1052         }
   1053         if ((it->second.gnssNmeaCb != nullptr) && (mNmeaMask)) {
   1054             mask |= LOC_API_ADAPTER_BIT_NMEA_1HZ_REPORT;
   1055         }
   1056         if (it->second.gnssMeasurementsCb != nullptr) {
   1057             mask |= LOC_API_ADAPTER_BIT_GNSS_MEASUREMENT;
   1058         }
   1059     }
   1060 
   1061     /*
   1062     ** For Automotive use cases we need to enable MEASUREMENT and POLY
   1063     ** when QDR is enabled
   1064     */
   1065     if(1 == ContextBase::mGps_conf.EXTERNAL_DR_ENABLED) {
   1066         mask |= LOC_API_ADAPTER_BIT_GNSS_MEASUREMENT;
   1067         mask |= LOC_API_ADAPTER_BIT_GNSS_SV_POLYNOMIAL_REPORT;
   1068 
   1069         LOC_LOGD("%s]: Auto usecase, Enable MEAS/POLY - mask 0x%x", __func__, mask);
   1070     }
   1071 
   1072     updateEvtMask(mask, LOC_REGISTRATION_MASK_SET);
   1073 }
   1074 
   1075 void
   1076 GnssAdapter::handleEngineUpEvent()
   1077 {
   1078     struct MsgRestartSessions : public LocMsg {
   1079         GnssAdapter& mAdapter;
   1080         inline MsgRestartSessions(GnssAdapter& adapter) :
   1081             LocMsg(),
   1082             mAdapter(adapter) {}
   1083         virtual void proc() const {
   1084             mAdapter.restartSessions();
   1085         }
   1086     };
   1087 
   1088     setConfigCommand();
   1089     sendMsg(new MsgRestartSessions(*this));
   1090 }
   1091 
   1092 void
   1093 GnssAdapter::restartSessions()
   1094 {
   1095     LOC_LOGD("%s]: ", __func__);
   1096 
   1097     if (mTrackingSessions.empty()) {
   1098         return;
   1099     }
   1100 
   1101     // get the LocationOptions that has the smallest interval, which should be the active one
   1102     LocationOptions smallestIntervalOptions = {}; // size is zero until set for the first time
   1103     for (auto it = mTrackingSessions.begin(); it != mTrackingSessions.end(); ++it) {
   1104         if (0 == smallestIntervalOptions.size || //size of zero means we havent set it yet
   1105             it->second.minInterval < smallestIntervalOptions.minInterval) {
   1106              smallestIntervalOptions = it->second;
   1107         }
   1108     }
   1109 
   1110     LocPosMode locPosMode = {};
   1111     convertOptions(locPosMode, smallestIntervalOptions);
   1112     mLocApi->startFix(locPosMode);
   1113 }
   1114 
   1115 void
   1116 GnssAdapter::requestCapabilitiesCommand(LocationAPI* client)
   1117 {
   1118     LOC_LOGD("%s]: ", __func__);
   1119 
   1120     struct MsgRequestCapabilities : public LocMsg {
   1121         GnssAdapter& mAdapter;
   1122         LocationAPI* mClient;
   1123         inline MsgRequestCapabilities(GnssAdapter& adapter,
   1124                                       LocationAPI* client) :
   1125             LocMsg(),
   1126             mAdapter(adapter),
   1127             mClient(client) {}
   1128         inline virtual void proc() const {
   1129             LocationCallbacks callbacks = mAdapter.getClientCallbacks(mClient);
   1130             if (callbacks.capabilitiesCb == nullptr) {
   1131                 LOC_LOGE("%s]: capabilitiesCb is NULL", __func__);
   1132                 return;
   1133             }
   1134 
   1135             LocationCapabilitiesMask mask = mAdapter.getCapabilities();
   1136             callbacks.capabilitiesCb(mask);
   1137         }
   1138     };
   1139 
   1140     sendMsg(new MsgRequestCapabilities(*this, client));
   1141 }
   1142 
   1143 LocationCapabilitiesMask
   1144 GnssAdapter::getCapabilities()
   1145 {
   1146     LocationCapabilitiesMask mask = 0;
   1147     uint32_t carrierCapabilities = ContextBase::getCarrierCapabilities();
   1148     // time based tracking always supported
   1149     mask |= LOCATION_CAPABILITIES_TIME_BASED_TRACKING_BIT;
   1150     // geofence always supported
   1151     mask |= LOCATION_CAPABILITIES_GEOFENCE_BIT;
   1152     if (carrierCapabilities & LOC_GPS_CAPABILITY_MSB) {
   1153         mask |= LOCATION_CAPABILITIES_GNSS_MSB_BIT;
   1154     }
   1155     if (LOC_GPS_CAPABILITY_MSA & carrierCapabilities) {
   1156         mask |= LOCATION_CAPABILITIES_GNSS_MSA_BIT;
   1157     }
   1158     if (mLocApi == nullptr)
   1159         return mask;
   1160     if (mLocApi->isMessageSupported(LOC_API_ADAPTER_MESSAGE_DISTANCE_BASE_LOCATION_BATCHING)) {
   1161         mask |= LOCATION_CAPABILITIES_TIME_BASED_BATCHING_BIT |
   1162                 LOCATION_CAPABILITIES_DISTANCE_BASED_BATCHING_BIT;
   1163     }
   1164     if (mLocApi->isMessageSupported(LOC_API_ADAPTER_MESSAGE_DISTANCE_BASE_TRACKING)) {
   1165         mask |= LOCATION_CAPABILITIES_DISTANCE_BASED_TRACKING_BIT;
   1166     }
   1167     if (mLocApi->isMessageSupported(LOC_API_ADAPTER_MESSAGE_OUTDOOR_TRIP_BATCHING)) {
   1168         mask |= LOCATION_CAPABILITIES_OUTDOOR_TRIP_BATCHING_BIT;
   1169     }
   1170     if (mLocApi->gnssConstellationConfig()) {
   1171         mask |= LOCATION_CAPABILITIES_GNSS_MEASUREMENTS_BIT;
   1172     }
   1173     if (mLocApi->isFeatureSupported(LOC_SUPPORTED_FEATURE_DEBUG_NMEA_V02)) {
   1174         mask |= LOCATION_CAPABILITIES_DEBUG_NMEA_BIT;
   1175     }
   1176     return mask;
   1177 }
   1178 
   1179 void
   1180 GnssAdapter::broadcastCapabilities(LocationCapabilitiesMask mask)
   1181 {
   1182     for (auto it = mClientData.begin(); it != mClientData.end(); ++it) {
   1183         if (nullptr != it->second.capabilitiesCb) {
   1184             it->second.capabilitiesCb(mask);
   1185         }
   1186     }
   1187 }
   1188 
   1189 LocationCallbacks
   1190 GnssAdapter::getClientCallbacks(LocationAPI* client)
   1191 {
   1192     LocationCallbacks callbacks = {};
   1193     auto it = mClientData.find(client);
   1194     if (it != mClientData.end()) {
   1195         callbacks = it->second;
   1196     }
   1197     return callbacks;
   1198 }
   1199 
   1200 void
   1201 GnssAdapter::saveClient(LocationAPI* client, const LocationCallbacks& callbacks)
   1202 {
   1203     mClientData[client] = callbacks;
   1204     updateClientsEventMask();
   1205 }
   1206 
   1207 void
   1208 GnssAdapter::eraseClient(LocationAPI* client)
   1209 {
   1210     auto it = mClientData.find(client);
   1211     if (it != mClientData.end()) {
   1212         mClientData.erase(it);
   1213     }
   1214     updateClientsEventMask();
   1215 }
   1216 
   1217 bool
   1218 GnssAdapter::hasTrackingCallback(LocationAPI* client)
   1219 {
   1220     auto it = mClientData.find(client);
   1221     return (it != mClientData.end() && it->second.trackingCb);
   1222 }
   1223 
   1224 bool
   1225 GnssAdapter::hasMeasurementsCallback(LocationAPI* client)
   1226 {
   1227     auto it = mClientData.find(client);
   1228     return (it != mClientData.end() && it->second.gnssMeasurementsCb);
   1229 }
   1230 
   1231 bool
   1232 GnssAdapter::isTrackingSession(LocationAPI* client, uint32_t sessionId)
   1233 {
   1234     LocationSessionKey key(client, sessionId);
   1235     return (mTrackingSessions.find(key) != mTrackingSessions.end());
   1236 }
   1237 
   1238 void
   1239 GnssAdapter::saveTrackingSession(LocationAPI* client, uint32_t sessionId,
   1240                                  const LocationOptions& options)
   1241 {
   1242     LocationSessionKey key(client, sessionId);
   1243     mTrackingSessions[key] = options;
   1244 }
   1245 
   1246 void
   1247 GnssAdapter::eraseTrackingSession(LocationAPI* client, uint32_t sessionId)
   1248 {
   1249     LocationSessionKey key(client, sessionId);
   1250     auto it = mTrackingSessions.find(key);
   1251     if (it != mTrackingSessions.end()) {
   1252         mTrackingSessions.erase(it);
   1253     }
   1254 
   1255 }
   1256 
   1257 void
   1258 GnssAdapter::reportResponse(LocationAPI* client, LocationError err, uint32_t sessionId)
   1259 {
   1260     LOC_LOGD("%s]: client %p id %u err %u", __func__, client, sessionId, err);
   1261 
   1262     auto it = mClientData.find(client);
   1263     if (it != mClientData.end() &&
   1264         it->second.responseCb != nullptr) {
   1265         it->second.responseCb(err, sessionId);
   1266     } else {
   1267         LOC_LOGW("%s]: client %p id %u not found in data", __func__, client, sessionId);
   1268     }
   1269 }
   1270 
   1271 void
   1272 GnssAdapter::reportResponse(LocationError err, uint32_t sessionId)
   1273 {
   1274     LOC_LOGD("%s]: id %u err %u", __func__, sessionId, err);
   1275 
   1276     if (mControlCallbacks.size > 0 && mControlCallbacks.responseCb != nullptr) {
   1277         mControlCallbacks.responseCb(err, sessionId);
   1278     } else {
   1279         LOC_LOGW("%s]: control client response callback not found", __func__);
   1280     }
   1281 }
   1282 
   1283 void
   1284 GnssAdapter::reportResponse(size_t count, LocationError* errs, uint32_t* ids)
   1285 {
   1286     IF_LOC_LOGD {
   1287         std::string idsString = "[";
   1288         std::string errsString = "[";
   1289         if (NULL != ids && NULL != errs) {
   1290             for (size_t i=0; i < count; ++i) {
   1291                 idsString += std::to_string(ids[i]) + " ";
   1292                 errsString += std::to_string(errs[i]) + " ";
   1293             }
   1294         }
   1295         idsString += "]";
   1296         errsString += "]";
   1297 
   1298         LOC_LOGD("%s]: ids %s errs %s",
   1299                  __func__, idsString.c_str(), errsString.c_str());
   1300     }
   1301 
   1302     if (mControlCallbacks.size > 0 && mControlCallbacks.collectiveResponseCb != nullptr) {
   1303         mControlCallbacks.collectiveResponseCb(count, errs, ids);
   1304     } else {
   1305         LOC_LOGW("%s]: control client callback not found", __func__);
   1306     }
   1307 }
   1308 
   1309 uint32_t
   1310 GnssAdapter::startTrackingCommand(LocationAPI* client, LocationOptions& options)
   1311 {
   1312     uint32_t sessionId = generateSessionId();
   1313     LOC_LOGD("%s]: client %p id %u minInterval %u mode %u",
   1314              __func__, client, sessionId, options.minInterval, options.mode);
   1315 
   1316     struct MsgStartTracking : public LocMsg {
   1317         GnssAdapter& mAdapter;
   1318         LocApiBase& mApi;
   1319         LocationAPI* mClient;
   1320         uint32_t mSessionId;
   1321         LocationOptions mOptions;
   1322         inline MsgStartTracking(GnssAdapter& adapter,
   1323                                LocApiBase& api,
   1324                                LocationAPI* client,
   1325                                uint32_t sessionId,
   1326                                LocationOptions options) :
   1327             LocMsg(),
   1328             mAdapter(adapter),
   1329             mApi(api),
   1330             mClient(client),
   1331             mSessionId(sessionId),
   1332             mOptions(options) {}
   1333         inline virtual void proc() const {
   1334             LocationError err = LOCATION_ERROR_SUCCESS;
   1335             if (!mAdapter.hasTrackingCallback(mClient) &&
   1336                 !mAdapter.hasMeasurementsCallback(mClient)) {
   1337                 err = LOCATION_ERROR_CALLBACK_MISSING;
   1338             } else if (0 == mOptions.size) {
   1339                 err = LOCATION_ERROR_INVALID_PARAMETER;
   1340             } else {
   1341                 // Api doesn't support multiple clients for time based tracking, so mutiplex
   1342                 err = mAdapter.startTrackingMultiplex(mOptions);
   1343                 if (LOCATION_ERROR_SUCCESS == err) {
   1344                     mAdapter.saveTrackingSession(mClient, mSessionId, mOptions);
   1345                 }
   1346             }
   1347             mAdapter.reportResponse(mClient, err, mSessionId);
   1348         }
   1349     };
   1350 
   1351     sendMsg(new MsgStartTracking(*this, *mLocApi, client, sessionId, options));
   1352     return sessionId;
   1353 
   1354 }
   1355 
   1356 LocationError
   1357 GnssAdapter::startTrackingMultiplex(const LocationOptions& options)
   1358 {
   1359     LocationError err = LOCATION_ERROR_SUCCESS;
   1360 
   1361     if (mTrackingSessions.empty()) {
   1362         err = startTracking(options);
   1363     } else {
   1364         // get the LocationOptions that has the smallest interval, which should be the active one
   1365         LocationOptions smallestIntervalOptions = {}; // size is zero until set for the first time
   1366         for (auto it = mTrackingSessions.begin(); it != mTrackingSessions.end(); ++it) {
   1367             if (0 == smallestIntervalOptions.size || //size of zero means we havent set it yet
   1368                 it->second.minInterval < smallestIntervalOptions.minInterval) {
   1369                  smallestIntervalOptions = it->second;
   1370             }
   1371         }
   1372         // if new session's minInterval is smaller than any in other sessions
   1373         if (options.minInterval < smallestIntervalOptions.minInterval) {
   1374             // restart time based tracking with new options
   1375             err = startTracking(options);
   1376         }
   1377     }
   1378 
   1379     return err;
   1380 }
   1381 
   1382 LocationError
   1383 GnssAdapter::startTracking(const LocationOptions& options)
   1384 {
   1385     LocationError err = LOCATION_ERROR_SUCCESS;
   1386     LocPosMode locPosMode = {};
   1387     convertOptions(locPosMode, options);
   1388     if (!mUlpProxy->sendFixMode(locPosMode)) {
   1389         // do nothing
   1390     }
   1391     if (!mUlpProxy->sendStartFix()) {
   1392         loc_api_adapter_err apiErr = mLocApi->startFix(locPosMode);
   1393         if (LOC_API_ADAPTER_ERR_SUCCESS == apiErr) {
   1394             err = LOCATION_ERROR_SUCCESS;
   1395         } else {
   1396             err = LOCATION_ERROR_GENERAL_FAILURE;
   1397         }
   1398     }
   1399 
   1400     return err;
   1401 }
   1402 
   1403 void
   1404 GnssAdapter::setPositionModeCommand(LocPosMode& locPosMode)
   1405 {
   1406     LOC_LOGD("%s]: min_interval %u mode %u",
   1407              __func__, locPosMode.min_interval, locPosMode.mode);
   1408 
   1409     struct MsgSetPositionMode : public LocMsg {
   1410         GnssAdapter& mAdapter;
   1411         LocApiBase& mApi;
   1412         LocPosMode mLocPosMode;
   1413         inline MsgSetPositionMode(GnssAdapter& adapter,
   1414                                   LocApiBase& api,
   1415                                   LocPosMode& locPosMode) :
   1416             LocMsg(),
   1417             mAdapter(adapter),
   1418             mApi(api),
   1419             mLocPosMode(locPosMode) {}
   1420         inline virtual void proc() const {
   1421              // saves the mode in adapter to be used when startTrackingCommand is called from ULP
   1422             mAdapter.setUlpPositionMode(mLocPosMode);
   1423             mApi.setPositionMode(mLocPosMode);
   1424         }
   1425     };
   1426 
   1427     sendMsg(new MsgSetPositionMode(*this, *mLocApi, locPosMode));
   1428 }
   1429 
   1430 void
   1431 GnssAdapter::startTrackingCommand()
   1432 {
   1433     LOC_LOGD("%s]: ", __func__);
   1434 
   1435     struct MsgStartTracking : public LocMsg {
   1436         GnssAdapter& mAdapter;
   1437         LocApiBase& mApi;
   1438         inline MsgStartTracking(GnssAdapter& adapter,
   1439                                 LocApiBase& api) :
   1440             LocMsg(),
   1441             mAdapter(adapter),
   1442             mApi(api) {}
   1443         inline virtual void proc() const {
   1444             // we get this call from ULP, so just call LocApi without multiplexing because
   1445             // ulp would be doing the multiplexing for us if it is present
   1446             LocPosMode& ulpPositionMode = mAdapter.getUlpPositionMode();
   1447             mApi.startFix(ulpPositionMode);
   1448         }
   1449     };
   1450 
   1451     sendMsg(new MsgStartTracking(*this, *mLocApi));
   1452 }
   1453 
   1454 void
   1455 GnssAdapter::updateTrackingOptionsCommand(LocationAPI* client, uint32_t id,
   1456                                           LocationOptions& options)
   1457 {
   1458     LOC_LOGD("%s]: client %p id %u minInterval %u mode %u",
   1459              __func__, client, id, options.minInterval, options.mode);
   1460 
   1461     struct MsgUpdateTracking : public LocMsg {
   1462         GnssAdapter& mAdapter;
   1463         LocApiBase& mApi;
   1464         LocationAPI* mClient;
   1465         uint32_t mSessionId;
   1466         LocationOptions mOptions;
   1467         inline MsgUpdateTracking(GnssAdapter& adapter,
   1468                                 LocApiBase& api,
   1469                                 LocationAPI* client,
   1470                                 uint32_t sessionId,
   1471                                 LocationOptions options) :
   1472             LocMsg(),
   1473             mAdapter(adapter),
   1474             mApi(api),
   1475             mClient(client),
   1476             mSessionId(sessionId),
   1477             mOptions(options) {}
   1478         inline virtual void proc() const {
   1479             if (mAdapter.isTrackingSession(mClient, mSessionId)) {
   1480                 LocationError err = LOCATION_ERROR_SUCCESS;
   1481                 if (0 == mOptions.size) {
   1482                     err = LOCATION_ERROR_INVALID_PARAMETER;
   1483                 } else {
   1484                     // Api doesn't support multiple clients for time based tracking, so mutiplex
   1485                     err = mAdapter.updateTrackingMultiplex(mClient, mSessionId, mOptions);
   1486                     if (LOCATION_ERROR_SUCCESS == err) {
   1487                         mAdapter.saveTrackingSession(mClient, mSessionId, mOptions);
   1488                     }
   1489                 }
   1490                 mAdapter.reportResponse(mClient, err, mSessionId);
   1491             }
   1492             // we do not reportResponse for the case where there is no existing tracking session
   1493             // for the client and id being used, since updateTrackingCommand can be sent to both
   1494             // GnssAdapter & FlpAdapter by LocationAPI and we want to avoid incorrect error response
   1495         }
   1496     };
   1497 
   1498     sendMsg(new MsgUpdateTracking(*this, *mLocApi, client, id, options));
   1499 }
   1500 
   1501 LocationError
   1502 GnssAdapter::updateTrackingMultiplex(LocationAPI* client, uint32_t id,
   1503                                      const LocationOptions& options)
   1504 {
   1505     LocationError err = LOCATION_ERROR_SUCCESS;
   1506 
   1507     if (1 == mTrackingSessions.size()) {
   1508         err = startTracking(options);
   1509     } else {
   1510         LocationSessionKey key(client, id);
   1511 
   1512         // get the session we are updating
   1513         auto it = mTrackingSessions.find(key);
   1514         if (it != mTrackingSessions.end()) {
   1515             // find the smallest interval, other than the session we are updating
   1516             LocationOptions smallestIntervalOptions = {}; // size is 0 until set for the first time
   1517             for (auto it2 = mTrackingSessions.begin(); it2 != mTrackingSessions.end(); ++it2) {
   1518                 // if session is not the one we are updating and either smallest interval is not set
   1519                 // or there is a new smallest interval, then set the new smallest interval
   1520                 if (it2->first != key && (0 == smallestIntervalOptions.size ||
   1521                     it2->second.minInterval < smallestIntervalOptions.minInterval)) {
   1522                      smallestIntervalOptions = it2->second;
   1523                 }
   1524             }
   1525             // if session we are updating has smaller interval then next smallest
   1526             if (options.minInterval < smallestIntervalOptions.minInterval) {
   1527                 // restart time based tracking with the newly updated interval
   1528                 err = startTracking(options);
   1529             // else if the session we are updating used to be the smallest
   1530             } else if (it->second.minInterval < smallestIntervalOptions.minInterval) {
   1531                 // restart time based tracking with the next smallest
   1532                 err = startTracking(smallestIntervalOptions);
   1533             }
   1534         }
   1535     }
   1536 
   1537     return err;
   1538 }
   1539 
   1540 void
   1541 GnssAdapter::stopTrackingCommand(LocationAPI* client, uint32_t id)
   1542 {
   1543     LOC_LOGD("%s]: client %p id %u", __func__, client, id);
   1544 
   1545     struct MsgStopTracking : public LocMsg {
   1546         GnssAdapter& mAdapter;
   1547         LocApiBase& mApi;
   1548         LocationAPI* mClient;
   1549         uint32_t mSessionId;
   1550         inline MsgStopTracking(GnssAdapter& adapter,
   1551                                LocApiBase& api,
   1552                                LocationAPI* client,
   1553                                uint32_t sessionId) :
   1554             LocMsg(),
   1555             mAdapter(adapter),
   1556             mApi(api),
   1557             mClient(client),
   1558             mSessionId(sessionId) {}
   1559         inline virtual void proc() const {
   1560             if (mAdapter.isTrackingSession(mClient, mSessionId)) {
   1561                 LocationError err = LOCATION_ERROR_SUCCESS;
   1562                 // Api doesn't support multiple clients for time based tracking, so mutiplex
   1563                 err = mAdapter.stopTrackingMultiplex(mClient, mSessionId);
   1564                 if (LOCATION_ERROR_SUCCESS == err) {
   1565                     mAdapter.eraseTrackingSession(mClient, mSessionId);
   1566                 }
   1567                 mAdapter.reportResponse(mClient, err, mSessionId);
   1568             }
   1569             // we do not reportResponse for the case where there is no existing tracking session
   1570             // for the client and id being used, since stopTrackingCommand can be sent to both
   1571             // GnssAdapter & FlpAdapter by LocationAPI and we want to avoid incorrect error response
   1572 
   1573         }
   1574     };
   1575 
   1576     sendMsg(new MsgStopTracking(*this, *mLocApi, client, id));
   1577 }
   1578 
   1579 LocationError
   1580 GnssAdapter::stopTrackingMultiplex(LocationAPI* client, uint32_t id)
   1581 {
   1582     LocationError err = LOCATION_ERROR_SUCCESS;
   1583 
   1584     if (1 == mTrackingSessions.size()) {
   1585         err = stopTracking();
   1586     } else {
   1587         LocationSessionKey key(client, id);
   1588 
   1589         // get the session we are stopping
   1590         auto it = mTrackingSessions.find(key);
   1591         if (it != mTrackingSessions.end()) {
   1592             // find the next smallest interval, other than the session we are stopping
   1593             LocationOptions smallestIntervalOptions = {}; // size is 0 until set for the first time
   1594             for (auto it2 = mTrackingSessions.begin(); it2 != mTrackingSessions.end(); ++it2) {
   1595                 // if session is not the one we are stopping and either smallest interval is not set
   1596                 // or there is a new smallest interval, then set the new smallest interval
   1597                 if (it2->first != key && (0 == smallestIntervalOptions.size ||
   1598                     it2->second.minInterval < smallestIntervalOptions.minInterval)) {
   1599                      smallestIntervalOptions = it2->second;
   1600                 }
   1601             }
   1602             // if session we are stopping has smaller interval then next smallest
   1603             if (it->second.minInterval < smallestIntervalOptions.minInterval) {
   1604                 // restart time based tracking with next smallest interval
   1605                 err = startTracking(smallestIntervalOptions);
   1606             }
   1607         }
   1608     }
   1609 
   1610     return err;
   1611 }
   1612 
   1613 LocationError
   1614 GnssAdapter::stopTracking()
   1615 {
   1616     LocationError err = LOCATION_ERROR_SUCCESS;
   1617     if (!mUlpProxy->sendStopFix()) {
   1618         loc_api_adapter_err apiErr = mLocApi->stopFix();
   1619         if (LOC_API_ADAPTER_ERR_SUCCESS == apiErr) {
   1620             err = LOCATION_ERROR_SUCCESS;
   1621         } else {
   1622             err = LOCATION_ERROR_GENERAL_FAILURE;
   1623         }
   1624     }
   1625 
   1626     return err;
   1627 }
   1628 
   1629 void
   1630 GnssAdapter::stopTrackingCommand()
   1631 {
   1632     LOC_LOGD("%s]: ", __func__);
   1633 
   1634     struct MsgStopTracking : public LocMsg {
   1635         GnssAdapter& mAdapter;
   1636         LocApiBase& mApi;
   1637         inline MsgStopTracking(GnssAdapter& adapter,
   1638                                LocApiBase& api) :
   1639             LocMsg(),
   1640             mAdapter(adapter),
   1641             mApi(api) {}
   1642         inline virtual void proc() const {
   1643             // clear the position mode
   1644             LocPosMode mLocPosMode = {};
   1645             mLocPosMode.mode = LOC_POSITION_MODE_INVALID;
   1646             mAdapter.setUlpPositionMode(mLocPosMode);
   1647             // don't need to multiplex because ULP will do that for us if it is present
   1648             mApi.stopFix();
   1649         }
   1650     };
   1651 
   1652     sendMsg(new MsgStopTracking(*this, *mLocApi));
   1653 }
   1654 
   1655 void
   1656 GnssAdapter::getZppCommand()
   1657 {
   1658     LOC_LOGD("%s]: ", __func__);
   1659 
   1660     struct MsgGetZpp : public LocMsg {
   1661         GnssAdapter& mAdapter;
   1662         LocApiBase& mApi;
   1663         inline MsgGetZpp(GnssAdapter& adapter,
   1664                          LocApiBase& api) :
   1665             LocMsg(),
   1666             mAdapter(adapter),
   1667             mApi(api) {}
   1668         inline virtual void proc() const {
   1669             UlpLocation location = {};
   1670             LocPosTechMask techMask = LOC_POS_TECH_MASK_DEFAULT;
   1671             GpsLocationExtended locationExtended = {};
   1672             locationExtended.size = sizeof(locationExtended);
   1673 
   1674             mApi.getBestAvailableZppFix(location.gpsLocation, locationExtended,
   1675                     techMask);
   1676             //Mark the location source as from ZPP
   1677             location.gpsLocation.flags |= LOCATION_HAS_SOURCE_INFO;
   1678             location.position_source = ULP_LOCATION_IS_FROM_ZPP;
   1679 
   1680             mAdapter.getUlpProxy()->reportPosition(location,
   1681                                                    locationExtended,
   1682                                                    LOC_SESS_SUCCESS,
   1683                                                    techMask);
   1684         }
   1685     };
   1686 
   1687     sendMsg(new MsgGetZpp(*this, *mLocApi));
   1688 }
   1689 
   1690 bool
   1691 GnssAdapter::hasNiNotifyCallback(LocationAPI* client)
   1692 {
   1693     auto it = mClientData.find(client);
   1694     return (it != mClientData.end() && it->second.gnssNiCb);
   1695 }
   1696 
   1697 void
   1698 GnssAdapter::gnssNiResponseCommand(LocationAPI* client,
   1699                                    uint32_t id,
   1700                                    GnssNiResponse response)
   1701 {
   1702     LOC_LOGD("%s]: client %p id %u response %u", __func__, client, id, response);
   1703 
   1704     struct MsgGnssNiResponse : public LocMsg {
   1705         GnssAdapter& mAdapter;
   1706         LocationAPI* mClient;
   1707         uint32_t mSessionId;
   1708         GnssNiResponse mResponse;
   1709         inline MsgGnssNiResponse(GnssAdapter& adapter,
   1710                                  LocationAPI* client,
   1711                                  uint32_t sessionId,
   1712                                  GnssNiResponse response) :
   1713             LocMsg(),
   1714             mAdapter(adapter),
   1715             mClient(client),
   1716             mSessionId(sessionId),
   1717             mResponse(response) {}
   1718         inline virtual void proc() const {
   1719             NiData& niData = mAdapter.getNiData();
   1720             LocationError err = LOCATION_ERROR_SUCCESS;
   1721             if (!mAdapter.hasNiNotifyCallback(mClient)) {
   1722                 err = LOCATION_ERROR_ID_UNKNOWN;
   1723             } else {
   1724                 NiSession* pSession = NULL;
   1725                 if (mSessionId == niData.sessionEs.reqID &&
   1726                     NULL != niData.sessionEs.rawRequest) {
   1727                     pSession = &niData.sessionEs;
   1728                     // ignore any SUPL NI non-Es session if a SUPL NI ES is accepted
   1729                     if (mResponse == GNSS_NI_RESPONSE_ACCEPT &&
   1730                         NULL != niData.session.rawRequest) {
   1731                             pthread_mutex_lock(&niData.session.tLock);
   1732                             niData.session.resp = GNSS_NI_RESPONSE_IGNORE;
   1733                             niData.session.respRecvd = true;
   1734                             pthread_cond_signal(&niData.session.tCond);
   1735                             pthread_mutex_unlock(&niData.session.tLock);
   1736                     }
   1737                 } else if (mSessionId == niData.session.reqID &&
   1738                     NULL != niData.session.rawRequest) {
   1739                     pSession = &niData.session;
   1740                 }
   1741 
   1742                 if (pSession) {
   1743                     LOC_LOGI("%s]: gnssNiResponseCommand: send user mResponse %u for id %u",
   1744                              __func__, mResponse, mSessionId);
   1745                     pthread_mutex_lock(&pSession->tLock);
   1746                     pSession->resp = mResponse;
   1747                     pSession->respRecvd = true;
   1748                     pthread_cond_signal(&pSession->tCond);
   1749                     pthread_mutex_unlock(&pSession->tLock);
   1750                 } else {
   1751                     err = LOCATION_ERROR_ID_UNKNOWN;
   1752                     LOC_LOGE("%s]: gnssNiResponseCommand: id %u not an active session",
   1753                              __func__, mSessionId);
   1754                 }
   1755             }
   1756             mAdapter.reportResponse(mClient, err, mSessionId);
   1757         }
   1758     };
   1759 
   1760     sendMsg(new MsgGnssNiResponse(*this, client, id, response));
   1761 
   1762 }
   1763 
   1764 void
   1765 GnssAdapter::gnssNiResponseCommand(GnssNiResponse response, void* rawRequest)
   1766 {
   1767     LOC_LOGD("%s]: response %u", __func__, response);
   1768 
   1769     struct MsgGnssNiResponse : public LocMsg {
   1770         LocApiBase& mApi;
   1771         const GnssNiResponse mResponse;
   1772         const void* mPayload;
   1773         inline MsgGnssNiResponse(LocApiBase& api,
   1774                                  const GnssNiResponse response,
   1775                                  const void* rawRequest) :
   1776             LocMsg(),
   1777             mApi(api),
   1778             mResponse(response),
   1779             mPayload(rawRequest) {}
   1780         inline virtual ~MsgGnssNiResponse() {
   1781             // this is a bit weird since mPayload is not
   1782             // allocated by this class.  But there is no better way.
   1783             // mPayload actually won't be NULL here.
   1784             free((void*)mPayload);
   1785         }
   1786         inline virtual void proc() const {
   1787             mApi.informNiResponse(mResponse, mPayload);
   1788         }
   1789     };
   1790 
   1791     sendMsg(new MsgGnssNiResponse(*mLocApi, response, rawRequest));
   1792 
   1793 }
   1794 
   1795 uint32_t
   1796 GnssAdapter::enableCommand(LocationTechnologyType techType)
   1797 {
   1798     uint32_t sessionId = generateSessionId();
   1799     LOC_LOGD("%s]: id %u techType %u", __func__, sessionId, techType);
   1800 
   1801     struct MsgEnableGnss : public LocMsg {
   1802         GnssAdapter& mAdapter;
   1803         LocApiBase& mApi;
   1804         ContextBase& mContext;
   1805         uint32_t mSessionId;
   1806         LocationTechnologyType mTechType;
   1807         inline MsgEnableGnss(GnssAdapter& adapter,
   1808                              LocApiBase& api,
   1809                              ContextBase& context,
   1810                              uint32_t sessionId,
   1811                              LocationTechnologyType techType) :
   1812             LocMsg(),
   1813             mAdapter(adapter),
   1814             mApi(api),
   1815             mContext(context),
   1816             mSessionId(sessionId),
   1817             mTechType(techType) {}
   1818         inline virtual void proc() const {
   1819             LocationError err = LOCATION_ERROR_SUCCESS;
   1820             uint32_t powerVoteId = mAdapter.getPowerVoteId();
   1821             if (mTechType != LOCATION_TECHNOLOGY_TYPE_GNSS) {
   1822                 err = LOCATION_ERROR_INVALID_PARAMETER;
   1823             } else if (powerVoteId > 0) {
   1824                 err = LOCATION_ERROR_ALREADY_STARTED;
   1825             } else {
   1826                 mContext.modemPowerVote(true);
   1827                 mAdapter.setPowerVoteId(mSessionId);
   1828                 mApi.setGpsLock(GNSS_CONFIG_GPS_LOCK_NONE);
   1829                 mAdapter.mXtraObserver.updateLockStatus(
   1830                         mAdapter.convertGpsLock(GNSS_CONFIG_GPS_LOCK_NONE));
   1831             }
   1832             mAdapter.reportResponse(err, mSessionId);
   1833         }
   1834     };
   1835 
   1836     if (mContext != NULL) {
   1837         sendMsg(new MsgEnableGnss(*this, *mLocApi, *mContext, sessionId, techType));
   1838     } else {
   1839         LOC_LOGE("%s]: Context is NULL", __func__);
   1840     }
   1841 
   1842     return sessionId;
   1843 }
   1844 
   1845 void
   1846 GnssAdapter::disableCommand(uint32_t id)
   1847 {
   1848     LOC_LOGD("%s]: id %u", __func__, id);
   1849 
   1850     struct MsgDisableGnss : public LocMsg {
   1851         GnssAdapter& mAdapter;
   1852         LocApiBase& mApi;
   1853         ContextBase& mContext;
   1854         uint32_t mSessionId;
   1855         inline MsgDisableGnss(GnssAdapter& adapter,
   1856                              LocApiBase& api,
   1857                              ContextBase& context,
   1858                              uint32_t sessionId) :
   1859             LocMsg(),
   1860             mAdapter(adapter),
   1861             mApi(api),
   1862             mContext(context),
   1863             mSessionId(sessionId) {}
   1864         inline virtual void proc() const {
   1865             LocationError err = LOCATION_ERROR_SUCCESS;
   1866             uint32_t powerVoteId = mAdapter.getPowerVoteId();
   1867             if (powerVoteId != mSessionId) {
   1868                 err = LOCATION_ERROR_ID_UNKNOWN;
   1869             } else {
   1870                 mContext.modemPowerVote(false);
   1871                 mAdapter.setPowerVoteId(0);
   1872                 mApi.setGpsLock(mAdapter.convertGpsLock(ContextBase::mGps_conf.GPS_LOCK));
   1873                 mAdapter.mXtraObserver.updateLockStatus(
   1874                         mAdapter.convertGpsLock(ContextBase::mGps_conf.GPS_LOCK));
   1875             }
   1876             mAdapter.reportResponse(err, mSessionId);
   1877         }
   1878     };
   1879 
   1880     if (mContext != NULL) {
   1881         sendMsg(new MsgDisableGnss(*this, *mLocApi, *mContext, id));
   1882     }
   1883 
   1884 }
   1885 
   1886 void
   1887 GnssAdapter::reportPositionEvent(const UlpLocation& ulpLocation,
   1888                                  const GpsLocationExtended& locationExtended,
   1889                                  enum loc_sess_status status,
   1890                                  LocPosTechMask techMask,
   1891                                  bool fromUlp)
   1892 {
   1893     LOC_LOGD("%s]: fromUlp %u status %u", __func__, fromUlp, status);
   1894 
   1895     // if this event is not called from ULP, then try to call into ULP and return if successfull
   1896     if (!fromUlp) {
   1897         if (mUlpProxy->reportPosition(ulpLocation, locationExtended,
   1898                                  status, techMask)) {
   1899             return;
   1900         }
   1901     }
   1902 
   1903     struct MsgReportPosition : public LocMsg {
   1904         GnssAdapter& mAdapter;
   1905         const UlpLocation mUlpLocation;
   1906         const GpsLocationExtended mLocationExtended;
   1907         loc_sess_status mStatus;
   1908         LocPosTechMask mTechMask;
   1909         inline MsgReportPosition(GnssAdapter& adapter,
   1910                                  const UlpLocation& ulpLocation,
   1911                                  const GpsLocationExtended& locationExtended,
   1912                                  loc_sess_status status,
   1913                                  LocPosTechMask techMask) :
   1914             LocMsg(),
   1915             mAdapter(adapter),
   1916             mUlpLocation(ulpLocation),
   1917             mLocationExtended(locationExtended),
   1918             mStatus(status),
   1919             mTechMask(techMask) {}
   1920         inline virtual void proc() const {
   1921             // extract bug report info - this returns true if consumed by systemstatus
   1922             SystemStatus* s = mAdapter.getSystemStatus();
   1923             if ((nullptr != s) && (LOC_SESS_SUCCESS == mStatus)){
   1924                 s->eventPosition(mUlpLocation, mLocationExtended);
   1925             }
   1926             mAdapter.reportPosition(mUlpLocation, mLocationExtended, mStatus, mTechMask);
   1927         }
   1928     };
   1929 
   1930     sendMsg(new MsgReportPosition(*this, ulpLocation, locationExtended, status, techMask));
   1931 }
   1932 
   1933 void
   1934 GnssAdapter::reportPosition(const UlpLocation& ulpLocation,
   1935                             const GpsLocationExtended& locationExtended,
   1936                             enum loc_sess_status status,
   1937                             LocPosTechMask techMask)
   1938 {
   1939     bool reported = false;
   1940     // what's in the if is... (line by line)
   1941     // 1. this is a final fix; and
   1942     //   1.1 it is a Satellite fix; or
   1943     //   1.2 it is a sensor fix
   1944     // 2. (must be intermediate fix... implicit)
   1945     //   2.1 we accepte intermediate; and
   1946     //   2.2 it is NOT the case that
   1947     //   2.2.1 there is inaccuracy; and
   1948     //   2.2.2 we care about inaccuracy; and
   1949     //   2.2.3 the inaccuracy exceeds our tolerance
   1950     if ((LOC_SESS_SUCCESS == status &&
   1951               ((LOC_POS_TECH_MASK_SATELLITE |
   1952                 LOC_POS_TECH_MASK_SENSORS   |
   1953                 LOC_POS_TECH_MASK_HYBRID) &
   1954                techMask)) ||
   1955              (LOC_SESS_INTERMEDIATE == ContextBase::mGps_conf.INTERMEDIATE_POS &&
   1956               !((ulpLocation.gpsLocation.flags &
   1957                  LOC_GPS_LOCATION_HAS_ACCURACY) &&
   1958                 (ContextBase::mGps_conf.ACCURACY_THRES != 0) &&
   1959                 (ulpLocation.gpsLocation.accuracy >
   1960                  ContextBase::mGps_conf.ACCURACY_THRES)))) {
   1961         if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_GNSS_SV_USED_DATA) {
   1962             mGnssSvIdUsedInPosAvail = true;
   1963             mGnssSvIdUsedInPosition = locationExtended.gnss_sv_used_ids;
   1964         }
   1965         for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
   1966             if (nullptr != it->second.trackingCb) {
   1967                 Location location = {};
   1968                 convertLocation(location, ulpLocation.gpsLocation, locationExtended, techMask);
   1969                 it->second.trackingCb(location);
   1970             }
   1971             if (nullptr != it->second.gnssLocationInfoCb) {
   1972                 GnssLocationInfoNotification locationInfo = {};
   1973                 convertLocationInfo(locationInfo, locationExtended);
   1974                 it->second.gnssLocationInfoCb(locationInfo);
   1975             }
   1976         }
   1977         reported = true;
   1978     }
   1979 
   1980     if (NMEA_PROVIDER_AP == ContextBase::mGps_conf.NMEA_PROVIDER && !mTrackingSessions.empty()) {
   1981         /*Only BlankNMEA sentence needs to be processed and sent, if both lat, long is 0 &
   1982           horReliability is not set. */
   1983         bool blank_fix = ((0 == ulpLocation.gpsLocation.latitude) &&
   1984                           (0 == ulpLocation.gpsLocation.longitude) &&
   1985                           (LOC_RELIABILITY_NOT_SET == locationExtended.horizontal_reliability));
   1986         uint8_t generate_nmea = (reported && status != LOC_SESS_FAILURE && !blank_fix);
   1987         std::vector<std::string> nmeaArraystr;
   1988         loc_nmea_generate_pos(ulpLocation, locationExtended, generate_nmea, nmeaArraystr);
   1989         for (auto sentence : nmeaArraystr) {
   1990             reportNmea(sentence.c_str(), sentence.length());
   1991         }
   1992     }
   1993 
   1994     // Free the allocated memory for rawData
   1995     UlpLocation* gp = (UlpLocation*)&(ulpLocation);
   1996     if (gp != NULL && gp->rawData != NULL)
   1997     {
   1998         delete (char*)gp->rawData;
   1999         gp->rawData = NULL;
   2000         gp->rawDataSize = 0;
   2001     }
   2002 }
   2003 
   2004 void
   2005 GnssAdapter::reportSvEvent(const GnssSvNotification& svNotify,
   2006                            bool fromUlp)
   2007 {
   2008     LOC_LOGD("%s]: fromUlp %u", __func__, fromUlp);
   2009 
   2010     // if this event is not called from ULP, then try to call into ULP and return if successfull
   2011     if (!fromUlp) {
   2012         if (mUlpProxy->reportSv(svNotify)) {
   2013             return;
   2014         }
   2015     }
   2016 
   2017     struct MsgReportSv : public LocMsg {
   2018         GnssAdapter& mAdapter;
   2019         const GnssSvNotification mSvNotify;
   2020         inline MsgReportSv(GnssAdapter& adapter,
   2021                            const GnssSvNotification& svNotify) :
   2022             LocMsg(),
   2023             mAdapter(adapter),
   2024             mSvNotify(svNotify) {}
   2025         inline virtual void proc() const {
   2026             mAdapter.reportSv((GnssSvNotification&)mSvNotify);
   2027         }
   2028     };
   2029 
   2030     sendMsg(new MsgReportSv(*this, svNotify));
   2031 }
   2032 
   2033 void
   2034 GnssAdapter::reportSv(GnssSvNotification& svNotify)
   2035 {
   2036     int numSv = svNotify.count;
   2037     int16_t gnssSvId = 0;
   2038     uint64_t svUsedIdMask = 0;
   2039     for (int i=0; i < numSv; i++) {
   2040         svUsedIdMask = 0;
   2041         gnssSvId = svNotify.gnssSvs[i].svId;
   2042         switch (svNotify.gnssSvs[i].type) {
   2043             case GNSS_SV_TYPE_GPS:
   2044                 if (mGnssSvIdUsedInPosAvail) {
   2045                     svUsedIdMask = mGnssSvIdUsedInPosition.gps_sv_used_ids_mask;
   2046                 }
   2047                 break;
   2048             case GNSS_SV_TYPE_GLONASS:
   2049                 if (mGnssSvIdUsedInPosAvail) {
   2050                     svUsedIdMask = mGnssSvIdUsedInPosition.glo_sv_used_ids_mask;
   2051                 }
   2052                 break;
   2053             case GNSS_SV_TYPE_BEIDOU:
   2054                 if (mGnssSvIdUsedInPosAvail) {
   2055                     svUsedIdMask = mGnssSvIdUsedInPosition.bds_sv_used_ids_mask;
   2056                 }
   2057                 break;
   2058             case GNSS_SV_TYPE_GALILEO:
   2059                 if (mGnssSvIdUsedInPosAvail) {
   2060                     svUsedIdMask = mGnssSvIdUsedInPosition.gal_sv_used_ids_mask;
   2061                 }
   2062                 break;
   2063             case GNSS_SV_TYPE_QZSS:
   2064                 if (mGnssSvIdUsedInPosAvail) {
   2065                     svUsedIdMask = mGnssSvIdUsedInPosition.qzss_sv_used_ids_mask;
   2066                 }
   2067                 // QZSS SV id's need to reported as it is to framework, since
   2068                 // framework expects it as it is. See GnssStatus.java.
   2069                 // SV id passed to here by LocApi is 1-based.
   2070                 svNotify.gnssSvs[i].svId += (QZSS_SV_PRN_MIN - 1);
   2071                 break;
   2072             default:
   2073                 svUsedIdMask = 0;
   2074                 break;
   2075         }
   2076 
   2077         // If SV ID was used in previous position fix, then set USED_IN_FIX
   2078         // flag, else clear the USED_IN_FIX flag.
   2079         if (svUsedIdMask & (1 << (gnssSvId - 1))) {
   2080             svNotify.gnssSvs[i].gnssSvOptionsMask |= GNSS_SV_OPTIONS_USED_IN_FIX_BIT;
   2081         }
   2082     }
   2083 
   2084     for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
   2085         if (nullptr != it->second.gnssSvCb) {
   2086             it->second.gnssSvCb(svNotify);
   2087         }
   2088     }
   2089 
   2090     if (NMEA_PROVIDER_AP == ContextBase::mGps_conf.NMEA_PROVIDER && !mTrackingSessions.empty()) {
   2091         std::vector<std::string> nmeaArraystr;
   2092         loc_nmea_generate_sv(svNotify, nmeaArraystr);
   2093         for (auto sentence : nmeaArraystr) {
   2094             reportNmea(sentence.c_str(), sentence.length());
   2095         }
   2096     }
   2097 
   2098     mGnssSvIdUsedInPosAvail = false;
   2099 }
   2100 
   2101 void
   2102 GnssAdapter::reportNmeaEvent(const char* nmea, size_t length, bool fromUlp)
   2103 {
   2104     // if this event is not called from ULP, then try to call into ULP and return if successfull
   2105     if (!fromUlp && !loc_nmea_is_debug(nmea, length)) {
   2106         if (mUlpProxy->reportNmea(nmea, length)) {
   2107             return;
   2108         }
   2109     }
   2110 
   2111     struct MsgReportNmea : public LocMsg {
   2112         GnssAdapter& mAdapter;
   2113         const char* mNmea;
   2114         size_t mLength;
   2115         inline MsgReportNmea(GnssAdapter& adapter,
   2116                              const char* nmea,
   2117                              size_t length) :
   2118             LocMsg(),
   2119             mAdapter(adapter),
   2120             mNmea(new char[length+1]),
   2121             mLength(length) {
   2122                 if (mNmea == nullptr) {
   2123                     LOC_LOGE("%s] new allocation failed, fatal error.", __func__);
   2124                     return;
   2125                 }
   2126                 strlcpy((char*)mNmea, nmea, length+1);
   2127             }
   2128         inline virtual ~MsgReportNmea()
   2129         {
   2130             delete[] mNmea;
   2131         }
   2132         inline virtual void proc() const {
   2133             // extract bug report info - this returns true if consumed by systemstatus
   2134             bool ret = false;
   2135             SystemStatus* s = mAdapter.getSystemStatus();
   2136             if (nullptr != s) {
   2137                 ret = s->setNmeaString(mNmea, mLength);
   2138             }
   2139             if (false == ret) {
   2140                 // forward NMEA message to upper layer
   2141                 mAdapter.reportNmea(mNmea, mLength);
   2142             }
   2143         }
   2144     };
   2145 
   2146     sendMsg(new MsgReportNmea(*this, nmea, length));
   2147 }
   2148 
   2149 void
   2150 GnssAdapter::reportNmea(const char* nmea, size_t length)
   2151 {
   2152     GnssNmeaNotification nmeaNotification = {};
   2153     nmeaNotification.size = sizeof(GnssNmeaNotification);
   2154 
   2155     struct timeval tv;
   2156     gettimeofday(&tv, (struct timezone *) NULL);
   2157     int64_t now = tv.tv_sec * 1000LL + tv.tv_usec / 1000;
   2158     nmeaNotification.timestamp = now;
   2159     nmeaNotification.nmea = nmea;
   2160     nmeaNotification.length = length;
   2161 
   2162     for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
   2163         if (nullptr != it->second.gnssNmeaCb) {
   2164             it->second.gnssNmeaCb(nmeaNotification);
   2165         }
   2166     }
   2167 }
   2168 
   2169 bool
   2170 GnssAdapter::requestNiNotifyEvent(const GnssNiNotification &notify, const void* data)
   2171 {
   2172     LOC_LOGI("%s]: notif_type: %d, timeout: %d, default_resp: %d"
   2173              "requestor_id: %s (encoding: %d) text: %s text (encoding: %d) extras: %s",
   2174              __func__, notify.type, notify.timeout, notify.timeoutResponse,
   2175              notify.requestor, notify.requestorEncoding,
   2176              notify.message, notify.messageEncoding, notify.extras);
   2177 
   2178     struct MsgReportNiNotify : public LocMsg {
   2179         GnssAdapter& mAdapter;
   2180         const GnssNiNotification mNotify;
   2181         const void* mData;
   2182         inline MsgReportNiNotify(GnssAdapter& adapter,
   2183                                  const GnssNiNotification& notify,
   2184                                  const void* data) :
   2185             LocMsg(),
   2186             mAdapter(adapter),
   2187             mNotify(notify),
   2188             mData(data) {}
   2189         inline virtual void proc() const {
   2190             mAdapter.requestNiNotify(mNotify, mData);
   2191         }
   2192     };
   2193 
   2194     sendMsg(new MsgReportNiNotify(*this, notify, data));
   2195 
   2196     return true;
   2197 }
   2198 
   2199 static void* niThreadProc(void *args)
   2200 {
   2201     NiSession* pSession = (NiSession*)args;
   2202     int rc = 0;          /* return code from pthread calls */
   2203 
   2204     struct timeval present_time;
   2205     struct timespec expire_time;
   2206 
   2207     pthread_mutex_lock(&pSession->tLock);
   2208     /* Calculate absolute expire time */
   2209     gettimeofday(&present_time, NULL);
   2210     expire_time.tv_sec  = present_time.tv_sec + pSession->respTimeLeft;
   2211     expire_time.tv_nsec = present_time.tv_usec * 1000;
   2212     LOC_LOGD("%s]: time out set for abs time %ld with delay %d sec",
   2213              __func__, (long)expire_time.tv_sec, pSession->respTimeLeft);
   2214 
   2215     while (!pSession->respRecvd) {
   2216         rc = pthread_cond_timedwait(&pSession->tCond,
   2217                                     &pSession->tLock,
   2218                                     &expire_time);
   2219         if (rc == ETIMEDOUT) {
   2220             pSession->resp = GNSS_NI_RESPONSE_NO_RESPONSE;
   2221             LOC_LOGD("%s]: time out after valting for specified time. Ret Val %d",
   2222                      __func__, rc);
   2223             break;
   2224         }
   2225     }
   2226     LOC_LOGD("%s]: Java layer has sent us a user response and return value from "
   2227              "pthread_cond_timedwait = %d pSession->resp is %u", __func__, rc, pSession->resp);
   2228     pSession->respRecvd = false; /* Reset the user response flag for the next session*/
   2229 
   2230     // adding this check to support modem restart, in which case, we need the thread
   2231     // to exit without calling sending data. We made sure that rawRequest is NULL in
   2232     // loc_eng_ni_reset_on_engine_restart()
   2233     GnssAdapter* adapter = pSession->adapter;
   2234     GnssNiResponse resp;
   2235     void* rawRequest = NULL;
   2236     bool sendResponse = false;
   2237 
   2238     if (NULL != pSession->rawRequest) {
   2239         if (pSession->resp != GNSS_NI_RESPONSE_IGNORE) {
   2240             resp = pSession->resp;
   2241             rawRequest = pSession->rawRequest;
   2242             sendResponse = true;
   2243         } else {
   2244             free(pSession->rawRequest);
   2245         }
   2246         pSession->rawRequest = NULL;
   2247     }
   2248     pthread_mutex_unlock(&pSession->tLock);
   2249 
   2250     pSession->respTimeLeft = 0;
   2251     pSession->reqID = 0;
   2252 
   2253     if (sendResponse) {
   2254         adapter->gnssNiResponseCommand(resp, rawRequest);
   2255     }
   2256 
   2257     return NULL;
   2258 }
   2259 
   2260 bool
   2261 GnssAdapter::requestNiNotify(const GnssNiNotification& notify, const void* data)
   2262 {
   2263     NiSession* pSession = NULL;
   2264     gnssNiCallback gnssNiCb = nullptr;
   2265 
   2266     for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
   2267         if (nullptr != it->second.gnssNiCb) {
   2268             gnssNiCb = it->second.gnssNiCb;
   2269             break;
   2270         }
   2271     }
   2272     if (nullptr == gnssNiCb) {
   2273         EXIT_LOG(%s, "no clients with gnssNiCb.");
   2274         return false;
   2275     }
   2276 
   2277     if (notify.type == GNSS_NI_TYPE_EMERGENCY_SUPL) {
   2278         if (NULL != mNiData.sessionEs.rawRequest) {
   2279             LOC_LOGI("%s]: supl es NI in progress, new supl es NI ignored, type: %d",
   2280                      __func__, notify.type);
   2281             if (NULL != data) {
   2282                 free((void*)data);
   2283             }
   2284         } else {
   2285             pSession = &mNiData.sessionEs;
   2286         }
   2287     } else {
   2288         if (NULL != mNiData.session.rawRequest ||
   2289             NULL != mNiData.sessionEs.rawRequest) {
   2290             LOC_LOGI("%s]: supl NI in progress, new supl NI ignored, type: %d",
   2291                      __func__, notify.type);
   2292             if (NULL != data) {
   2293                 free((void*)data);
   2294             }
   2295         } else {
   2296             pSession = &mNiData.session;
   2297         }
   2298     }
   2299 
   2300     if (pSession) {
   2301         /* Save request */
   2302         pSession->rawRequest = (void*)data;
   2303         pSession->reqID = ++mNiData.reqIDCounter;
   2304         pSession->adapter = this;
   2305 
   2306         int sessionId = pSession->reqID;
   2307 
   2308         /* For robustness, spawn a thread at this point to timeout to clear up the notification
   2309          * status, even though the OEM layer in java does not do so.
   2310          **/
   2311         pSession->respTimeLeft =
   2312              5 + (notify.timeout != 0 ? notify.timeout : LOC_NI_NO_RESPONSE_TIME);
   2313 
   2314         int rc = 0;
   2315         rc = pthread_create(&pSession->thread, NULL, niThreadProc, pSession);
   2316         if (rc) {
   2317             LOC_LOGE("%s]: Loc NI thread is not created.", __func__);
   2318         }
   2319         rc = pthread_detach(pSession->thread);
   2320         if (rc) {
   2321             LOC_LOGE("%s]: Loc NI thread is not detached.", __func__);
   2322         }
   2323 
   2324         if (nullptr != gnssNiCb) {
   2325             gnssNiCb(sessionId, notify);
   2326         }
   2327     }
   2328 
   2329     return true;
   2330 }
   2331 
   2332 void
   2333 GnssAdapter::reportGnssMeasurementDataEvent(const GnssMeasurementsNotification& measurements,
   2334                                             int msInWeek)
   2335 {
   2336     LOC_LOGD("%s]: ", __func__);
   2337 
   2338     struct MsgReportGnssMeasurementData : public LocMsg {
   2339         GnssAdapter& mAdapter;
   2340         GnssMeasurementsNotification mMeasurementsNotify;
   2341         inline MsgReportGnssMeasurementData(GnssAdapter& adapter,
   2342                                             const GnssMeasurementsNotification& measurements,
   2343                                             int msInWeek) :
   2344                 LocMsg(),
   2345                 mAdapter(adapter),
   2346                 mMeasurementsNotify(measurements) {
   2347             if (-1 != msInWeek) {
   2348                 mAdapter.getAgcInformation(mMeasurementsNotify, msInWeek);
   2349             }
   2350         }
   2351         inline virtual void proc() const {
   2352             mAdapter.reportGnssMeasurementData(mMeasurementsNotify);
   2353         }
   2354     };
   2355 
   2356     sendMsg(new MsgReportGnssMeasurementData(*this, measurements, msInWeek));
   2357 }
   2358 
   2359 void
   2360 GnssAdapter::reportGnssMeasurementData(const GnssMeasurementsNotification& measurements)
   2361 {
   2362     for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
   2363         if (nullptr != it->second.gnssMeasurementsCb) {
   2364             it->second.gnssMeasurementsCb(measurements);
   2365         }
   2366     }
   2367 }
   2368 
   2369 void
   2370 GnssAdapter::reportSvMeasurementEvent(GnssSvMeasurementSet &svMeasurementSet)
   2371 {
   2372     LOC_LOGD("%s]: ", __func__);
   2373 
   2374     // We send SvMeasurementSet to AmtProxy/ULPProxy to be forwarded as necessary.
   2375     mUlpProxy->reportSvMeasurement(svMeasurementSet);
   2376 }
   2377 
   2378 void
   2379 GnssAdapter::reportSvPolynomialEvent(GnssSvPolynomial &svPolynomial)
   2380 {
   2381     LOC_LOGD("%s]: ", __func__);
   2382 
   2383     // We send SvMeasurementSet to AmtProxy/ULPProxy to be forwarded as necessary.
   2384     mUlpProxy->reportSvPolynomial(svPolynomial);
   2385 }
   2386 
   2387 /* INIT LOC AGPS MANAGER */
   2388 void GnssAdapter::initAgpsCommand(const AgpsCbInfo& cbInfo){
   2389 
   2390     LOC_LOGI("GnssAdapter::initAgpsCommand");
   2391 
   2392     /* Set ATL open/close callbacks */
   2393     AgpsAtlOpenStatusCb atlOpenStatusCb =
   2394             [this](int handle, int isSuccess, char* apn,
   2395                     AGpsBearerType bearerType, AGpsExtType agpsType) {
   2396 
   2397                 mLocApi->atlOpenStatus(
   2398                         handle, isSuccess, apn, bearerType, agpsType);
   2399             };
   2400     AgpsAtlCloseStatusCb atlCloseStatusCb =
   2401             [this](int handle, int isSuccess) {
   2402 
   2403                 mLocApi->atlCloseStatus(handle, isSuccess);
   2404             };
   2405 
   2406     /* Register DS Client APIs */
   2407     AgpsDSClientInitFn dsClientInitFn =
   2408             [this](bool isDueToSSR) {
   2409 
   2410                 return mLocApi->initDataServiceClient(isDueToSSR);
   2411             };
   2412 
   2413     AgpsDSClientOpenAndStartDataCallFn dsClientOpenAndStartDataCallFn =
   2414             [this] {
   2415 
   2416                 return mLocApi->openAndStartDataCall();
   2417             };
   2418 
   2419     AgpsDSClientStopDataCallFn dsClientStopDataCallFn =
   2420             [this] {
   2421 
   2422                 mLocApi->stopDataCall();
   2423             };
   2424 
   2425     AgpsDSClientCloseDataCallFn dsClientCloseDataCallFn =
   2426             [this] {
   2427 
   2428                 mLocApi->closeDataCall();
   2429             };
   2430 
   2431     AgpsDSClientReleaseFn dsClientReleaseFn =
   2432             [this] {
   2433 
   2434                 mLocApi->releaseDataServiceClient();
   2435             };
   2436 
   2437     /* Send Msg function */
   2438     SendMsgToAdapterMsgQueueFn sendMsgFn =
   2439             [this](LocMsg* msg) {
   2440 
   2441                 sendMsg(msg);
   2442             };
   2443 
   2444     /* Message to initialize AGPS module */
   2445     struct AgpsMsgInit: public LocMsg {
   2446 
   2447         AgpsManager* mAgpsManager;
   2448 
   2449         AgpsFrameworkInterface::AgnssStatusIpV4Cb mFrameworkStatusV4Cb;
   2450 
   2451         AgpsAtlOpenStatusCb mAtlOpenStatusCb;
   2452         AgpsAtlCloseStatusCb mAtlCloseStatusCb;
   2453 
   2454         AgpsDSClientInitFn mDSClientInitFn;
   2455         AgpsDSClientOpenAndStartDataCallFn mDSClientOpenAndStartDataCallFn;
   2456         AgpsDSClientStopDataCallFn mDSClientStopDataCallFn;
   2457         AgpsDSClientCloseDataCallFn mDSClientCloseDataCallFn;
   2458         AgpsDSClientReleaseFn mDSClientReleaseFn;
   2459 
   2460         SendMsgToAdapterMsgQueueFn mSendMsgFn;
   2461         GnssAdapter& mAdapter;
   2462 
   2463         inline AgpsMsgInit(AgpsManager* agpsManager,
   2464                 AgpsFrameworkInterface::AgnssStatusIpV4Cb frameworkStatusV4Cb,
   2465                 AgpsAtlOpenStatusCb atlOpenStatusCb,
   2466                 AgpsAtlCloseStatusCb atlCloseStatusCb,
   2467                 AgpsDSClientInitFn dsClientInitFn,
   2468                 AgpsDSClientOpenAndStartDataCallFn dsClientOpenAndStartDataCallFn,
   2469                 AgpsDSClientStopDataCallFn dsClientStopDataCallFn,
   2470                 AgpsDSClientCloseDataCallFn dsClientCloseDataCallFn,
   2471                 AgpsDSClientReleaseFn dsClientReleaseFn,
   2472                 SendMsgToAdapterMsgQueueFn sendMsgFn,
   2473                 GnssAdapter& adapter) :
   2474                 LocMsg(), mAgpsManager(agpsManager), mFrameworkStatusV4Cb(
   2475                         frameworkStatusV4Cb), mAtlOpenStatusCb(atlOpenStatusCb), mAtlCloseStatusCb(
   2476                         atlCloseStatusCb), mDSClientInitFn(dsClientInitFn), mDSClientOpenAndStartDataCallFn(
   2477                         dsClientOpenAndStartDataCallFn), mDSClientStopDataCallFn(
   2478                         dsClientStopDataCallFn), mDSClientCloseDataCallFn(
   2479                         dsClientCloseDataCallFn), mDSClientReleaseFn(
   2480                         dsClientReleaseFn), mSendMsgFn(sendMsgFn),
   2481                         mAdapter(adapter) {
   2482 
   2483             LOC_LOGV("AgpsMsgInit");
   2484         }
   2485 
   2486         inline virtual void proc() const {
   2487 
   2488             LOC_LOGV("AgpsMsgInit::proc()");
   2489 
   2490             mAgpsManager->registerCallbacks(mFrameworkStatusV4Cb, mAtlOpenStatusCb,
   2491                     mAtlCloseStatusCb, mDSClientInitFn,
   2492                     mDSClientOpenAndStartDataCallFn, mDSClientStopDataCallFn,
   2493                     mDSClientCloseDataCallFn, mDSClientReleaseFn, mSendMsgFn);
   2494 
   2495             mAgpsManager->createAgpsStateMachines();
   2496 
   2497             /* Register for AGPS event mask */
   2498             mAdapter.updateEvtMask(LOC_API_ADAPTER_BIT_LOCATION_SERVER_REQUEST,
   2499                                    LOC_REGISTRATION_MASK_ENABLED);
   2500         }
   2501     };
   2502 
   2503     if (mAgpsCbInfo.cbPriority > cbInfo.cbPriority) {
   2504         LOC_LOGI("Higher priority AGPS CB already registered (%d > %d) !",
   2505                 mAgpsCbInfo.cbPriority, cbInfo.cbPriority);
   2506         return;
   2507     } else {
   2508         mAgpsCbInfo = cbInfo;
   2509         LOC_LOGI("Registering AGPS CB %p with priority %d",
   2510                 mAgpsCbInfo.statusV4Cb, mAgpsCbInfo.cbPriority);
   2511     }
   2512 
   2513     /* Send message to initialize AGPS Manager */
   2514     sendMsg(new AgpsMsgInit(
   2515                 &mAgpsManager,
   2516                 (AgpsFrameworkInterface::AgnssStatusIpV4Cb)cbInfo.statusV4Cb,
   2517                 atlOpenStatusCb, atlCloseStatusCb,
   2518                 dsClientInitFn, dsClientOpenAndStartDataCallFn,
   2519                 dsClientStopDataCallFn, dsClientCloseDataCallFn,
   2520                 dsClientReleaseFn,
   2521                 sendMsgFn,
   2522                 *this));
   2523 }
   2524 
   2525 /* GnssAdapter::requestATL
   2526  * Method triggered in QMI thread as part of handling below message:
   2527  * eQMI_LOC_SERVER_REQUEST_OPEN_V02
   2528  * Triggers the AGPS state machine to setup AGPS call for below WWAN types:
   2529  * eQMI_LOC_WWAN_TYPE_INTERNET_V02
   2530  * eQMI_LOC_WWAN_TYPE_AGNSS_V02 */
   2531 bool GnssAdapter::requestATL(int connHandle, LocAGpsType agpsType){
   2532 
   2533     LOC_LOGI("GnssAdapter::requestATL");
   2534 
   2535     sendMsg( new AgpsMsgRequestATL(
   2536              &mAgpsManager, connHandle, (AGpsExtType)agpsType));
   2537 
   2538     return true;
   2539 }
   2540 
   2541 /* GnssAdapter::requestSuplES
   2542  * Method triggered in QMI thread as part of handling below message:
   2543  * eQMI_LOC_SERVER_REQUEST_OPEN_V02
   2544  * Triggers the AGPS state machine to setup AGPS call for below WWAN types:
   2545  * eQMI_LOC_WWAN_TYPE_AGNSS_EMERGENCY_V02 */
   2546 bool GnssAdapter::requestSuplES(int connHandle){
   2547 
   2548     LOC_LOGI("GnssAdapter::requestSuplES");
   2549 
   2550     sendMsg( new AgpsMsgRequestATL(
   2551              &mAgpsManager, connHandle, LOC_AGPS_TYPE_SUPL_ES));
   2552 
   2553     return true;
   2554 }
   2555 
   2556 /* GnssAdapter::releaseATL
   2557  * Method triggered in QMI thread as part of handling below message:
   2558  * eQMI_LOC_SERVER_REQUEST_CLOSE_V02
   2559  * Triggers teardown of an existing AGPS call */
   2560 bool GnssAdapter::releaseATL(int connHandle){
   2561 
   2562     LOC_LOGI("GnssAdapter::releaseATL");
   2563 
   2564     /* Release SUPL/INTERNET/SUPL_ES ATL */
   2565     struct AgpsMsgReleaseATL: public LocMsg {
   2566 
   2567         AgpsManager* mAgpsManager;
   2568         int mConnHandle;
   2569 
   2570         inline AgpsMsgReleaseATL(AgpsManager* agpsManager, int connHandle) :
   2571                 LocMsg(), mAgpsManager(agpsManager), mConnHandle(connHandle) {
   2572 
   2573             LOC_LOGV("AgpsMsgReleaseATL");
   2574         }
   2575 
   2576         inline virtual void proc() const {
   2577 
   2578             LOC_LOGV("AgpsMsgReleaseATL::proc()");
   2579             mAgpsManager->releaseATL(mConnHandle);
   2580         }
   2581     };
   2582 
   2583     sendMsg( new AgpsMsgReleaseATL(&mAgpsManager, connHandle));
   2584 
   2585     return true;
   2586 }
   2587 
   2588 /* GnssAdapter::reportDataCallOpened
   2589  * DS Client data call opened successfully.
   2590  * Send message to AGPS Manager to handle. */
   2591 bool GnssAdapter::reportDataCallOpened(){
   2592 
   2593     LOC_LOGI("GnssAdapter::reportDataCallOpened");
   2594 
   2595     struct AgpsMsgSuplEsOpened: public LocMsg {
   2596 
   2597         AgpsManager* mAgpsManager;
   2598 
   2599         inline AgpsMsgSuplEsOpened(AgpsManager* agpsManager) :
   2600                 LocMsg(), mAgpsManager(agpsManager) {
   2601 
   2602             LOC_LOGV("AgpsMsgSuplEsOpened");
   2603         }
   2604 
   2605         inline virtual void proc() const {
   2606 
   2607             LOC_LOGV("AgpsMsgSuplEsOpened::proc()");
   2608             mAgpsManager->reportDataCallOpened();
   2609         }
   2610     };
   2611 
   2612     sendMsg( new AgpsMsgSuplEsOpened(&mAgpsManager));
   2613 
   2614     return true;
   2615 }
   2616 
   2617 /* GnssAdapter::reportDataCallClosed
   2618  * DS Client data call closed.
   2619  * Send message to AGPS Manager to handle. */
   2620 bool GnssAdapter::reportDataCallClosed(){
   2621 
   2622     LOC_LOGI("GnssAdapter::reportDataCallClosed");
   2623 
   2624     struct AgpsMsgSuplEsClosed: public LocMsg {
   2625 
   2626         AgpsManager* mAgpsManager;
   2627 
   2628         inline AgpsMsgSuplEsClosed(AgpsManager* agpsManager) :
   2629                 LocMsg(), mAgpsManager(agpsManager) {
   2630 
   2631             LOC_LOGV("AgpsMsgSuplEsClosed");
   2632         }
   2633 
   2634         inline virtual void proc() const {
   2635 
   2636             LOC_LOGV("AgpsMsgSuplEsClosed::proc()");
   2637             mAgpsManager->reportDataCallClosed();
   2638         }
   2639     };
   2640 
   2641     sendMsg( new AgpsMsgSuplEsClosed(&mAgpsManager));
   2642 
   2643     return true;
   2644 }
   2645 
   2646 void GnssAdapter::dataConnOpenCommand(
   2647         AGpsExtType agpsType,
   2648         const char* apnName, int apnLen, LocApnIpType ipType){
   2649 
   2650     LOC_LOGI("GnssAdapter::frameworkDataConnOpen");
   2651 
   2652     struct AgpsMsgAtlOpenSuccess: public LocMsg {
   2653 
   2654         AgpsManager* mAgpsManager;
   2655         AGpsExtType mAgpsType;
   2656         char* mApnName;
   2657         int mApnLen;
   2658         LocApnIpType mIpType;
   2659 
   2660         inline AgpsMsgAtlOpenSuccess(AgpsManager* agpsManager, AGpsExtType agpsType,
   2661                 const char* apnName, int apnLen, LocApnIpType ipType) :
   2662                 LocMsg(), mAgpsManager(agpsManager), mAgpsType(agpsType), mApnName(
   2663                         new char[apnLen + 1]), mApnLen(apnLen), mIpType(ipType) {
   2664 
   2665             LOC_LOGV("AgpsMsgAtlOpenSuccess");
   2666             if (mApnName == nullptr) {
   2667                 LOC_LOGE("%s] new allocation failed, fatal error.", __func__);
   2668                 return;
   2669             }
   2670             memcpy(mApnName, apnName, apnLen);
   2671             mApnName[apnLen] = 0;
   2672         }
   2673 
   2674         inline ~AgpsMsgAtlOpenSuccess() {
   2675             delete[] mApnName;
   2676         }
   2677 
   2678         inline virtual void proc() const {
   2679 
   2680             LOC_LOGV("AgpsMsgAtlOpenSuccess::proc()");
   2681             mAgpsManager->reportAtlOpenSuccess(mAgpsType, mApnName, mApnLen,
   2682                     mIpType);
   2683         }
   2684     };
   2685 
   2686     sendMsg( new AgpsMsgAtlOpenSuccess(
   2687             &mAgpsManager, (AGpsExtType)agpsType, apnName, apnLen, ipType));
   2688 }
   2689 
   2690 void GnssAdapter::dataConnClosedCommand(AGpsExtType agpsType){
   2691 
   2692     LOC_LOGI("GnssAdapter::frameworkDataConnClosed");
   2693 
   2694     struct AgpsMsgAtlClosed: public LocMsg {
   2695 
   2696         AgpsManager* mAgpsManager;
   2697         AGpsExtType mAgpsType;
   2698 
   2699         inline AgpsMsgAtlClosed(AgpsManager* agpsManager, AGpsExtType agpsType) :
   2700                 LocMsg(), mAgpsManager(agpsManager), mAgpsType(agpsType) {
   2701 
   2702             LOC_LOGV("AgpsMsgAtlClosed");
   2703         }
   2704 
   2705         inline virtual void proc() const {
   2706 
   2707             LOC_LOGV("AgpsMsgAtlClosed::proc()");
   2708             mAgpsManager->reportAtlClosed(mAgpsType);
   2709         }
   2710     };
   2711 
   2712     sendMsg( new AgpsMsgAtlClosed(&mAgpsManager, (AGpsExtType)agpsType));
   2713 }
   2714 
   2715 void GnssAdapter::dataConnFailedCommand(AGpsExtType agpsType){
   2716 
   2717     LOC_LOGI("GnssAdapter::frameworkDataConnFailed");
   2718 
   2719     struct AgpsMsgAtlOpenFailed: public LocMsg {
   2720 
   2721         AgpsManager* mAgpsManager;
   2722         AGpsExtType mAgpsType;
   2723 
   2724         inline AgpsMsgAtlOpenFailed(AgpsManager* agpsManager, AGpsExtType agpsType) :
   2725                 LocMsg(), mAgpsManager(agpsManager), mAgpsType(agpsType) {
   2726 
   2727             LOC_LOGV("AgpsMsgAtlOpenFailed");
   2728         }
   2729 
   2730         inline virtual void proc() const {
   2731 
   2732             LOC_LOGV("AgpsMsgAtlOpenFailed::proc()");
   2733             mAgpsManager->reportAtlOpenFailed(mAgpsType);
   2734         }
   2735     };
   2736 
   2737     sendMsg( new AgpsMsgAtlOpenFailed(&mAgpsManager, (AGpsExtType)agpsType));
   2738 }
   2739 
   2740 void GnssAdapter::convertSatelliteInfo(std::vector<GnssDebugSatelliteInfo>& out,
   2741                                        const GnssSvType& in_constellation,
   2742                                        const SystemStatusReports& in)
   2743 {
   2744     uint64_t sv_mask = 0ULL;
   2745     uint32_t svid_min = 0;
   2746     uint32_t svid_num = 0;
   2747     uint32_t svid_idx = 0;
   2748 
   2749     uint64_t eph_health_good_mask = 0ULL;
   2750     uint64_t eph_health_bad_mask = 0ULL;
   2751     uint64_t server_perdiction_available_mask = 0ULL;
   2752     float server_perdiction_age = 0.0f;
   2753 
   2754     // set constellationi based parameters
   2755     switch (in_constellation) {
   2756         case GNSS_SV_TYPE_GPS:
   2757             svid_min = GNSS_BUGREPORT_GPS_MIN;
   2758             svid_num = GPS_NUM;
   2759             svid_idx = 0;
   2760             if (!in.mSvHealth.empty()) {
   2761                 eph_health_good_mask = in.mSvHealth.back().mGpsGoodMask;
   2762                 eph_health_bad_mask  = in.mSvHealth.back().mGpsBadMask;
   2763             }
   2764             if (!in.mXtra.empty()) {
   2765                 server_perdiction_available_mask = in.mXtra.back().mGpsXtraValid;
   2766                 server_perdiction_age = (float)(in.mXtra.back().mGpsXtraAge);
   2767             }
   2768             break;
   2769         case GNSS_SV_TYPE_GLONASS:
   2770             svid_min = GNSS_BUGREPORT_GLO_MIN;
   2771             svid_num = GLO_NUM;
   2772             svid_idx = GPS_NUM;
   2773             if (!in.mSvHealth.empty()) {
   2774                 eph_health_good_mask = in.mSvHealth.back().mGloGoodMask;
   2775                 eph_health_bad_mask  = in.mSvHealth.back().mGloBadMask;
   2776             }
   2777             if (!in.mXtra.empty()) {
   2778                 server_perdiction_available_mask = in.mXtra.back().mGloXtraValid;
   2779                 server_perdiction_age = (float)(in.mXtra.back().mGloXtraAge);
   2780             }
   2781             break;
   2782         case GNSS_SV_TYPE_QZSS:
   2783             svid_min = GNSS_BUGREPORT_QZSS_MIN;
   2784             svid_num = QZSS_NUM;
   2785             svid_idx = GPS_NUM+GLO_NUM+BDS_NUM+GAL_NUM;
   2786             if (!in.mSvHealth.empty()) {
   2787                 eph_health_good_mask = in.mSvHealth.back().mQzssGoodMask;
   2788                 eph_health_bad_mask  = in.mSvHealth.back().mQzssBadMask;
   2789             }
   2790             if (!in.mXtra.empty()) {
   2791                 server_perdiction_available_mask = in.mXtra.back().mQzssXtraValid;
   2792                 server_perdiction_age = (float)(in.mXtra.back().mQzssXtraAge);
   2793             }
   2794             break;
   2795         case GNSS_SV_TYPE_BEIDOU:
   2796             svid_min = GNSS_BUGREPORT_BDS_MIN;
   2797             svid_num = BDS_NUM;
   2798             svid_idx = GPS_NUM+GLO_NUM;
   2799             if (!in.mSvHealth.empty()) {
   2800                 eph_health_good_mask = in.mSvHealth.back().mBdsGoodMask;
   2801                 eph_health_bad_mask  = in.mSvHealth.back().mBdsBadMask;
   2802             }
   2803             if (!in.mXtra.empty()) {
   2804                 server_perdiction_available_mask = in.mXtra.back().mBdsXtraValid;
   2805                 server_perdiction_age = (float)(in.mXtra.back().mBdsXtraAge);
   2806             }
   2807             break;
   2808         case GNSS_SV_TYPE_GALILEO:
   2809             svid_min = GNSS_BUGREPORT_GAL_MIN;
   2810             svid_num = GAL_NUM;
   2811             svid_idx = GPS_NUM+GLO_NUM+BDS_NUM;
   2812             if (!in.mSvHealth.empty()) {
   2813                 eph_health_good_mask = in.mSvHealth.back().mGalGoodMask;
   2814                 eph_health_bad_mask  = in.mSvHealth.back().mGalBadMask;
   2815             }
   2816             if (!in.mXtra.empty()) {
   2817                 server_perdiction_available_mask = in.mXtra.back().mGalXtraValid;
   2818                 server_perdiction_age = (float)(in.mXtra.back().mGalXtraAge);
   2819             }
   2820             break;
   2821         default:
   2822             return;
   2823     }
   2824 
   2825     // extract each sv info from systemstatus report
   2826     for(uint32_t i=0; i<svid_num && (svid_idx+i)<SV_ALL_NUM; i++) {
   2827 
   2828         GnssDebugSatelliteInfo s = {};
   2829         s.size = sizeof(s);
   2830         s.svid = i + svid_min;
   2831         s.constellation = in_constellation;
   2832 
   2833         if (!in.mNavData.empty()) {
   2834             s.mEphemerisType   = in.mNavData.back().mNav[svid_idx+i].mType;
   2835             s.mEphemerisSource = in.mNavData.back().mNav[svid_idx+i].mSource;
   2836         }
   2837         else {
   2838             s.mEphemerisType   = GNSS_EPH_TYPE_UNKNOWN;
   2839             s.mEphemerisSource = GNSS_EPH_SOURCE_UNKNOWN;
   2840         }
   2841 
   2842         sv_mask = 0x1ULL << i;
   2843         if (eph_health_good_mask & sv_mask) {
   2844             s.mEphemerisHealth = GNSS_EPH_HEALTH_GOOD;
   2845         }
   2846         else if (eph_health_bad_mask & sv_mask) {
   2847             s.mEphemerisHealth = GNSS_EPH_HEALTH_BAD;
   2848         }
   2849         else {
   2850             s.mEphemerisHealth = GNSS_EPH_HEALTH_UNKNOWN;
   2851         }
   2852 
   2853         if (!in.mNavData.empty()) {
   2854             s.ephemerisAgeSeconds =
   2855                 (float)(in.mNavData.back().mNav[svid_idx+i].mAgeSec);
   2856         }
   2857         else {
   2858             s.ephemerisAgeSeconds = 0.0f;
   2859         }
   2860 
   2861         if (server_perdiction_available_mask & sv_mask) {
   2862             s.serverPredictionIsAvailable = true;
   2863         }
   2864         else {
   2865             s.serverPredictionIsAvailable = false;
   2866         }
   2867 
   2868         s.serverPredictionAgeSeconds = server_perdiction_age;
   2869         out.push_back(s);
   2870     }
   2871 
   2872     return;
   2873 }
   2874 
   2875 bool GnssAdapter::getDebugReport(GnssDebugReport& r)
   2876 {
   2877     LOC_LOGD("%s]: ", __func__);
   2878 
   2879     SystemStatus* systemstatus = getSystemStatus();
   2880     if (nullptr == systemstatus) {
   2881         return false;
   2882     }
   2883 
   2884     SystemStatusReports reports = {};
   2885     systemstatus->getReport(reports, true);
   2886 
   2887     r.size = sizeof(r);
   2888 
   2889     // location block
   2890     r.mLocation.size = sizeof(r.mLocation);
   2891     if(!reports.mLocation.empty() && reports.mLocation.back().mValid) {
   2892         r.mLocation.mValid = true;
   2893         r.mLocation.mLocation.latitude =
   2894             reports.mLocation.back().mLocation.gpsLocation.latitude;
   2895         r.mLocation.mLocation.longitude =
   2896             reports.mLocation.back().mLocation.gpsLocation.longitude;
   2897         r.mLocation.mLocation.altitude =
   2898             reports.mLocation.back().mLocation.gpsLocation.altitude;
   2899         r.mLocation.mLocation.speed =
   2900             (double)(reports.mLocation.back().mLocation.gpsLocation.speed);
   2901         r.mLocation.mLocation.bearing =
   2902             (double)(reports.mLocation.back().mLocation.gpsLocation.bearing);
   2903         r.mLocation.mLocation.accuracy =
   2904             (double)(reports.mLocation.back().mLocation.gpsLocation.accuracy);
   2905 
   2906         r.mLocation.verticalAccuracyMeters =
   2907             reports.mLocation.back().mLocationEx.vert_unc;
   2908         r.mLocation.speedAccuracyMetersPerSecond =
   2909             reports.mLocation.back().mLocationEx.speed_unc;
   2910         r.mLocation.bearingAccuracyDegrees =
   2911             reports.mLocation.back().mLocationEx.bearing_unc;
   2912 
   2913         r.mLocation.mUtcReported =
   2914             reports.mLocation.back().mUtcReported;
   2915     }
   2916     else if(!reports.mBestPosition.empty() && reports.mBestPosition.back().mValid) {
   2917         r.mLocation.mValid = true;
   2918         r.mLocation.mLocation.latitude  =
   2919             (double)(reports.mBestPosition.back().mBestLat);
   2920         r.mLocation.mLocation.longitude =
   2921             (double)(reports.mBestPosition.back().mBestLon);
   2922         r.mLocation.mLocation.altitude  =
   2923             reports.mBestPosition.back().mBestAlt;
   2924 
   2925         r.mLocation.mLocation.timestamp =
   2926             reports.mBestPosition.back().mUtcReported.tv_sec * 1000ULL +
   2927             reports.mBestPosition.back().mUtcReported.tv_nsec / 1000000ULL;
   2928     }
   2929     else {
   2930         r.mLocation.mValid = false;
   2931     }
   2932 
   2933     if (r.mLocation.mValid) {
   2934         LOC_LOGV("getDebugReport - lat=%f lon=%f alt=%f speed=%f",
   2935             r.mLocation.mLocation.latitude,
   2936             r.mLocation.mLocation.longitude,
   2937             r.mLocation.mLocation.altitude,
   2938             r.mLocation.mLocation.speed);
   2939     }
   2940 
   2941     // time block
   2942     r.mTime.size = sizeof(r.mTime);
   2943     if(!reports.mTimeAndClock.empty() && reports.mTimeAndClock.back().mTimeValid) {
   2944         r.mTime.mValid = true;
   2945         r.mTime.timeEstimate =
   2946             (((int64_t)(reports.mTimeAndClock.back().mGpsWeek)*7 +
   2947                         GNSS_UTC_TIME_OFFSET)*24*60*60 -
   2948               (int64_t)(reports.mTimeAndClock.back().mLeapSeconds))*1000ULL +
   2949               (int64_t)(reports.mTimeAndClock.back().mGpsTowMs);
   2950 
   2951         r.mTime.timeUncertaintyNs =
   2952             (float)((reports.mTimeAndClock.back().mTimeUnc +
   2953                      reports.mTimeAndClock.back().mLeapSecUnc)*1000);
   2954         r.mTime.frequencyUncertaintyNsPerSec =
   2955             (float)(reports.mTimeAndClock.back().mClockFreqBiasUnc);
   2956         LOC_LOGV("getDebugReport - timeestimate=%" PRIu64 " unc=%f frequnc=%f",
   2957                 r.mTime.timeEstimate,
   2958                 r.mTime.timeUncertaintyNs, r.mTime.frequencyUncertaintyNsPerSec);
   2959     }
   2960     else {
   2961         r.mTime.mValid = false;
   2962     }
   2963 
   2964     // satellite info block
   2965     convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_GPS, reports);
   2966     convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_GLONASS, reports);
   2967     convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_QZSS, reports);
   2968     convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_BEIDOU, reports);
   2969     convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_GALILEO, reports);
   2970     LOC_LOGV("getDebugReport - satellite=%zu", r.mSatelliteInfo.size());
   2971 
   2972     return true;
   2973 }
   2974 
   2975 /* get AGC information from system status and fill it */
   2976 void
   2977 GnssAdapter::getAgcInformation(GnssMeasurementsNotification& measurements, int msInWeek)
   2978 {
   2979     SystemStatus* systemstatus = getSystemStatus();
   2980 
   2981     if (nullptr != systemstatus) {
   2982         SystemStatusReports reports = {};
   2983         systemstatus->getReport(reports, true);
   2984 
   2985         if ((!reports.mRfAndParams.empty()) && (!reports.mTimeAndClock.empty()) &&
   2986             reports.mTimeAndClock.back().mTimeValid &&
   2987             (abs(msInWeek - (int)reports.mTimeAndClock.back().mGpsTowMs) < 2000)) {
   2988 
   2989             for (size_t i = 0; i < measurements.count; i++) {
   2990                 switch (measurements.measurements[i].svType) {
   2991                 case GNSS_SV_TYPE_GPS:
   2992                     measurements.measurements[i].agcLevelDb =
   2993                             reports.mRfAndParams.back().mAgcGps;
   2994                     measurements.measurements[i].flags |=
   2995                             GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT;
   2996                     break;
   2997 
   2998                 case GNSS_SV_TYPE_GALILEO:
   2999                     measurements.measurements[i].agcLevelDb =
   3000                             reports.mRfAndParams.back().mAgcGal;
   3001                     measurements.measurements[i].flags |=
   3002                             GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT;
   3003                     break;
   3004 
   3005                 case GNSS_SV_TYPE_GLONASS:
   3006                     measurements.measurements[i].agcLevelDb =
   3007                             reports.mRfAndParams.back().mAgcGlo;
   3008                     measurements.measurements[i].flags |=
   3009                             GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT;
   3010                     break;
   3011 
   3012                 case GNSS_SV_TYPE_BEIDOU:
   3013                     measurements.measurements[i].agcLevelDb =
   3014                             reports.mRfAndParams.back().mAgcBds;
   3015                     measurements.measurements[i].flags |=
   3016                             GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT;
   3017                     break;
   3018 
   3019                 case GNSS_SV_TYPE_QZSS:
   3020                 case GNSS_SV_TYPE_SBAS:
   3021                 case GNSS_SV_TYPE_UNKNOWN:
   3022                 default:
   3023                     break;
   3024                 }
   3025             }
   3026         }
   3027     }
   3028 }
   3029 
   3030