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