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