1 /* Copyright (c) 2017-2021 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_NDEBUG 0
30 #define LOG_TAG "LocSvc_GnssAdapter"
31 
32 #include <inttypes.h>
33 #include <sys/stat.h>
34 #include <errno.h>
35 #include <ctype.h>
36 #include <cutils/properties.h>
37 #include <math.h>
38 #include <arpa/inet.h>
39 #include <netinet/in.h>
40 #include <netdb.h>
41 #include <GnssAdapter.h>
42 #include <string>
43 #include <sstream>
44 #include <loc_log.h>
45 #include <loc_nmea.h>
46 #include <Agps.h>
47 #include <SystemStatus.h>
48 #include <vector>
49 #include <loc_misc_utils.h>
50 #include <gps_extended_c.h>
51 
52 #define RAD2DEG    (180.0 / M_PI)
53 #define DEG2RAD    (M_PI / 180.0)
54 #define PROCESS_NAME_ENGINE_SERVICE "engine-service"
55 #define MIN_TRACKING_INTERVAL (100) // 100 msec
56 
57 #define BILLION_NSEC (1000000000ULL)
58 #define NMEA_MIN_THRESHOLD_MSEC (99)
59 #define NMEA_MAX_THRESHOLD_MSEC (975)
60 
61 #define DGNSS_RANGE_UPDATE_TIME_10MIN_IN_MILLI  600000
62 
63 using namespace loc_core;
64 
65 static int loadEngHubForExternalEngine = 0;
66 static loc_param_s_type izatConfParamTable[] = {
67     {"LOAD_ENGHUB_FOR_EXTERNAL_ENGINE", &loadEngHubForExternalEngine, nullptr,'n'}
68 };
69 
70 /* Method to fetch status cb from loc_net_iface library */
71 typedef AgpsCbInfo& (*LocAgpsGetAgpsCbInfo)(LocAgpsOpenResultCb openResultCb,
72         LocAgpsCloseResultCb closeResultCb, void* userDataPtr);
73 
74 static void agpsOpenResultCb (bool isSuccess, AGpsExtType agpsType, const char* apn,
75         AGpsBearerType bearerType, void* userDataPtr);
76 static void agpsCloseResultCb (bool isSuccess, AGpsExtType agpsType, void* userDataPtr);
77 
78 typedef const CdfwInterface* (*getCdfwInterface)();
79 
isLogEnabled()80 inline bool GnssReportLoggerUtil::isLogEnabled() {
81     return (mLogLatency != nullptr);
82 }
83 
log(const GnssLatencyInfo & gnssLatencyMeasInfo)84 inline void GnssReportLoggerUtil::log(const GnssLatencyInfo& gnssLatencyMeasInfo) {
85     if (mLogLatency != nullptr) {
86         mLogLatency(gnssLatencyMeasInfo);
87     }
88 }
89 
GnssAdapter()90 GnssAdapter::GnssAdapter() :
91     LocAdapterBase(0,
92                    LocContext::getLocContext(LocContext::mLocationHalName),
93                    true, nullptr, true),
94     mEngHubProxy(new EngineHubProxyBase()),
95     mQDgnssListenerHDL(nullptr),
96     mCdfwInterface(nullptr),
97     mDGnssNeedReport(false),
98     mDGnssDataUsage(false),
99     mLocPositionMode(),
100     mNHzNeeded(false),
101     mSPEAlreadyRunningAtHighestInterval(false),
102     mGnssSvIdUsedInPosition(),
103     mGnssSvIdUsedInPosAvail(false),
104     mControlCallbacks(),
105     mAfwControlId(0),
106     mNmeaMask(0),
107     mGnssSvIdConfig(),
108     mGnssSeconaryBandConfig(),
109     mGnssSvTypeConfig(),
110     mGnssSvTypeConfigCb(nullptr),
111     mLocConfigInfo{},
112     mNiData(),
113     mAgpsManager(),
114     mOdcpiRequestCb(nullptr),
115     mOdcpiRequestActive(false),
116     mOdcpiTimer(this),
117     mOdcpiRequest(),
118     mCallbackPriority(OdcpiPrioritytype::ODCPI_HANDLER_PRIORITY_LOW),
119     mSystemStatus(SystemStatus::getInstance(mMsgTask)),
120     mServerUrl(":"),
121     mXtraObserver(mSystemStatus->getOsObserver(), mMsgTask),
122     mBlockCPIInfo{},
123     mDreIntEnabled(false),
124     mLocSystemInfo{},
125     mNfwCb(NULL),
126     mPowerOn(false),
127     mAllowFlpNetworkFixes(0),
128     mGnssEnergyConsumedCb(nullptr),
129     mPowerStateCb(nullptr),
130     mIsE911Session(NULL),
131     mGnssMbSvIdUsedInPosition{},
132     mGnssMbSvIdUsedInPosAvail(false),
133     mSupportNfwControl(true),
134     mSystemPowerState(POWER_STATE_UNKNOWN),
135     mIsMeasCorrInterfaceOpen(false),
136     mIsAntennaInfoInterfaceOpened(false),
137     mLastDeleteAidingDataTime(0),
138     mDgnssState(0),
139     mSendNmeaConsent(false),
140     mDgnssLastNmeaBootTimeMilli(0),
141     mNativeAgpsHandler(mSystemStatus->getOsObserver(), *this)
142 {
143     LOC_LOGD("%s]: Constructor %p", __func__, this);
144     mLocPositionMode.mode = LOC_POSITION_MODE_INVALID;
145 
146     pthread_condattr_t condAttr;
147     pthread_condattr_init(&condAttr);
148     pthread_condattr_setclock(&condAttr, CLOCK_MONOTONIC);
149     pthread_cond_init(&mNiData.session.tCond, &condAttr);
150     pthread_cond_init(&mNiData.sessionEs.tCond, &condAttr);
151     pthread_condattr_destroy(&condAttr);
152 
153     /* Set ATL open/close callbacks */
154     AgpsAtlOpenStatusCb atlOpenStatusCb =
155             [this](int handle, int isSuccess, char* apn, uint32_t apnLen,
__anon5c731c740102(int handle, int isSuccess, char* apn, uint32_t apnLen, AGpsBearerType bearerType, AGpsExtType agpsType, LocApnTypeMask mask) 156                     AGpsBearerType bearerType, AGpsExtType agpsType, LocApnTypeMask mask) {
157 
158                 mLocApi->atlOpenStatus(
159                         handle, isSuccess, apn, apnLen, bearerType, agpsType, mask);
160             };
161     AgpsAtlCloseStatusCb atlCloseStatusCb =
__anon5c731c740202(int handle, int isSuccess) 162             [this](int handle, int isSuccess) {
163 
164                 mLocApi->atlCloseStatus(handle, isSuccess);
165             };
166     mAgpsManager.registerATLCallbacks(atlOpenStatusCb, atlCloseStatusCb);
167 
168     readConfigCommand();
169     initDefaultAgpsCommand();
170     initEngHubProxyCommand();
171 
172     // at last step, let us inform adapater base that we are done
173     // with initialization, e.g.: ready to process handleEngineUpEvent
174     doneInit();
175 }
176 
177 void
setControlCallbacksCommand(LocationControlCallbacks & controlCallbacks)178 GnssAdapter::setControlCallbacksCommand(LocationControlCallbacks& controlCallbacks)
179 {
180     struct MsgSetControlCallbacks : public LocMsg {
181         GnssAdapter& mAdapter;
182         const LocationControlCallbacks mControlCallbacks;
183         inline MsgSetControlCallbacks(GnssAdapter& adapter,
184                                       LocationControlCallbacks& controlCallbacks) :
185             LocMsg(),
186             mAdapter(adapter),
187             mControlCallbacks(controlCallbacks) {}
188         inline virtual void proc() const {
189             mAdapter.setControlCallbacks(mControlCallbacks);
190         }
191     };
192 
193     sendMsg(new MsgSetControlCallbacks(*this, controlCallbacks));
194 }
195 
196 void
convertOptions(LocPosMode & out,const TrackingOptions & trackingOptions)197 GnssAdapter::convertOptions(LocPosMode& out, const TrackingOptions& trackingOptions)
198 {
199     switch (trackingOptions.mode) {
200     case GNSS_SUPL_MODE_MSB:
201         out.mode = LOC_POSITION_MODE_MS_BASED;
202         break;
203     case GNSS_SUPL_MODE_MSA:
204         out.mode = LOC_POSITION_MODE_MS_ASSISTED;
205         break;
206     default:
207         out.mode = LOC_POSITION_MODE_STANDALONE;
208         break;
209     }
210     out.share_position = true;
211     out.min_interval = trackingOptions.minInterval;
212     out.powerMode = trackingOptions.powerMode;
213     out.timeBetweenMeasurements = trackingOptions.tbm;
214 }
215 
216 bool
checkAndSetSPEToRunforNHz(TrackingOptions & out)217 GnssAdapter::checkAndSetSPEToRunforNHz(TrackingOptions & out) {
218 
219     // first check if NHz meas is needed at all, if not, just return false
220     // if a NHz capable engine is subscribed for NHz measurement or NHz positions,
221     // always run the SPE only session at 100ms TBF.
222     // If SPE session is already set to highest interval, no need to start it again.
223 
224     bool isSPERunningAtHighestInterval = false;
225 
226     if (!mNHzNeeded) {
227         LOC_LOGd("No nHz session needed.");
228     } else if (mSPEAlreadyRunningAtHighestInterval) {
229         LOC_LOGd("SPE is already running at highest interval.");
230         isSPERunningAtHighestInterval = true;
231     } else if (out.minInterval > MIN_TRACKING_INTERVAL) {
232         out.minInterval = MIN_TRACKING_INTERVAL;
233         LOC_LOGd("nHz session is needed, starting SPE only session at 100ms TBF.");
234         mSPEAlreadyRunningAtHighestInterval = true;
235     }
236 
237     return isSPERunningAtHighestInterval;
238 }
239 
240 
241 void
convertLocation(Location & out,const UlpLocation & ulpLocation,const GpsLocationExtended & locationExtended)242 GnssAdapter::convertLocation(Location& out, const UlpLocation& ulpLocation,
243                              const GpsLocationExtended& locationExtended)
244 {
245     memset(&out, 0, sizeof(Location));
246     out.size = sizeof(Location);
247     if (LOC_GPS_LOCATION_HAS_LAT_LONG & ulpLocation.gpsLocation.flags) {
248         out.flags |= LOCATION_HAS_LAT_LONG_BIT;
249         out.latitude = ulpLocation.gpsLocation.latitude;
250         out.longitude = ulpLocation.gpsLocation.longitude;
251     }
252     if (LOC_GPS_LOCATION_HAS_ALTITUDE & ulpLocation.gpsLocation.flags) {
253         out.flags |= LOCATION_HAS_ALTITUDE_BIT;
254         out.altitude = ulpLocation.gpsLocation.altitude;
255     }
256     if (LOC_GPS_LOCATION_HAS_SPEED & ulpLocation.gpsLocation.flags) {
257         out.flags |= LOCATION_HAS_SPEED_BIT;
258         out.speed = ulpLocation.gpsLocation.speed;
259     }
260     if (LOC_GPS_LOCATION_HAS_BEARING & ulpLocation.gpsLocation.flags) {
261         out.flags |= LOCATION_HAS_BEARING_BIT;
262         out.bearing = ulpLocation.gpsLocation.bearing;
263     }
264     if (LOC_GPS_LOCATION_HAS_ACCURACY & ulpLocation.gpsLocation.flags) {
265         out.flags |= LOCATION_HAS_ACCURACY_BIT;
266         out.accuracy = ulpLocation.gpsLocation.accuracy;
267     }
268     if (GPS_LOCATION_EXTENDED_HAS_VERT_UNC & locationExtended.flags) {
269         out.flags |= LOCATION_HAS_VERTICAL_ACCURACY_BIT;
270         out.verticalAccuracy = locationExtended.vert_unc;
271     }
272     if (GPS_LOCATION_EXTENDED_HAS_SPEED_UNC & locationExtended.flags) {
273         out.flags |= LOCATION_HAS_SPEED_ACCURACY_BIT;
274         out.speedAccuracy = locationExtended.speed_unc;
275     }
276     if (GPS_LOCATION_EXTENDED_HAS_BEARING_UNC & locationExtended.flags) {
277         out.flags |= LOCATION_HAS_BEARING_ACCURACY_BIT;
278         out.bearingAccuracy = locationExtended.bearing_unc;
279     }
280     if (GPS_LOCATION_EXTENDED_HAS_CONFORMITY_INDEX & locationExtended.flags) {
281         out.flags |= LOCATION_HAS_CONFORMITY_INDEX_BIT;
282         out.conformityIndex = locationExtended.conformityIndex;
283     }
284     out.timestamp = ulpLocation.gpsLocation.timestamp;
285     if (LOC_POS_TECH_MASK_SATELLITE & locationExtended.tech_mask) {
286         out.techMask |= LOCATION_TECHNOLOGY_GNSS_BIT;
287     }
288     if (LOC_POS_TECH_MASK_CELLID & locationExtended.tech_mask) {
289         out.techMask |= LOCATION_TECHNOLOGY_CELL_BIT;
290     }
291     if (LOC_POS_TECH_MASK_WIFI & locationExtended.tech_mask) {
292         out.techMask |= LOCATION_TECHNOLOGY_WIFI_BIT;
293     }
294     if (LOC_POS_TECH_MASK_SENSORS & locationExtended.tech_mask) {
295         out.techMask |= LOCATION_TECHNOLOGY_SENSORS_BIT;
296     }
297     if (LOC_POS_TECH_MASK_REFERENCE_LOCATION & locationExtended.tech_mask) {
298         out.techMask |= LOCATION_TECHNOLOGY_REFERENCE_LOCATION_BIT;
299     }
300     if (LOC_POS_TECH_MASK_INJECTED_COARSE_POSITION & locationExtended.tech_mask) {
301         out.techMask |= LOCATION_TECHNOLOGY_INJECTED_COARSE_POSITION_BIT;
302     }
303     if (LOC_POS_TECH_MASK_AFLT & locationExtended.tech_mask) {
304         out.techMask |= LOCATION_TECHNOLOGY_AFLT_BIT;
305     }
306     if (LOC_POS_TECH_MASK_HYBRID & locationExtended.tech_mask) {
307         out.techMask |= LOCATION_TECHNOLOGY_HYBRID_BIT;
308     }
309     if (LOC_POS_TECH_MASK_PPE & locationExtended.tech_mask) {
310         out.techMask |= LOCATION_TECHNOLOGY_PPE_BIT;
311     }
312     if (LOC_POS_TECH_MASK_VEH & locationExtended.tech_mask) {
313         out.techMask |= LOCATION_TECHNOLOGY_VEH_BIT;
314     }
315     if (LOC_POS_TECH_MASK_VIS & locationExtended.tech_mask) {
316         out.techMask |= LOCATION_TECHNOLOGY_VIS_BIT;
317     }
318     if (LOC_NAV_MASK_DGNSS_CORRECTION & locationExtended.navSolutionMask) {
319         out.techMask |= LOCATION_TECHNOLOGY_DGNSS_BIT;
320     }
321 
322     if (LOC_GPS_LOCATION_HAS_SPOOF_MASK & ulpLocation.gpsLocation.flags) {
323         out.flags |= LOCATION_HAS_SPOOF_MASK;
324         out.spoofMask = ulpLocation.gpsLocation.spoof_mask;
325     }
326     if (LOC_GPS_LOCATION_HAS_ELAPSED_REAL_TIME & ulpLocation.gpsLocation.flags) {
327         out.flags |= LOCATION_HAS_ELAPSED_REAL_TIME;
328         out.elapsedRealTime = ulpLocation.gpsLocation.elapsedRealTime;
329         out.elapsedRealTimeUnc = ulpLocation.gpsLocation.elapsedRealTimeUnc;
330     }
331 }
332 
333 /* This is utility routine that computes number of SV used
334    in the fix from the svUsedIdsMask.
335  */
336 #define MAX_SV_CNT_SUPPORTED_IN_ONE_CONSTELLATION 64
getNumSvUsed(uint64_t svUsedIdsMask,int totalSvCntInThisConstellation)337 uint16_t GnssAdapter::getNumSvUsed(uint64_t svUsedIdsMask,
338                                    int totalSvCntInThisConstellation)
339 {
340     if (totalSvCntInThisConstellation > MAX_SV_CNT_SUPPORTED_IN_ONE_CONSTELLATION) {
341         LOC_LOGe ("error: total SV count in this constellation %d exceeded limit of %d",
342                   totalSvCntInThisConstellation, MAX_SV_CNT_SUPPORTED_IN_ONE_CONSTELLATION);
343         return 0;
344     }
345 
346     uint16_t numSvUsed = 0;
347     uint64_t mask = 0x1;
348     for (int i = 0; i < totalSvCntInThisConstellation; i++) {
349         if (svUsedIdsMask & mask) {
350             numSvUsed++;
351         }
352         mask <<= 1;
353     }
354 
355     return numSvUsed;
356 }
357 
358 void
convertLocationInfo(GnssLocationInfoNotification & out,const GpsLocationExtended & locationExtended,enum loc_sess_status status)359 GnssAdapter::convertLocationInfo(GnssLocationInfoNotification& out,
360                                  const GpsLocationExtended& locationExtended,
361                                  enum loc_sess_status status)
362 {
363     out.size = sizeof(GnssLocationInfoNotification);
364     if (GPS_LOCATION_EXTENDED_HAS_ALTITUDE_MEAN_SEA_LEVEL & locationExtended.flags) {
365         out.flags |= GNSS_LOCATION_INFO_ALTITUDE_MEAN_SEA_LEVEL_BIT;
366         out.altitudeMeanSeaLevel = locationExtended.altitudeMeanSeaLevel;
367     }
368     if (GPS_LOCATION_EXTENDED_HAS_EXT_DOP & locationExtended.flags) {
369         out.flags |= (GNSS_LOCATION_INFO_DOP_BIT|GNSS_LOCATION_INFO_EXT_DOP_BIT);
370         out.pdop = locationExtended.extDOP.PDOP;
371         out.hdop = locationExtended.extDOP.HDOP;
372         out.vdop = locationExtended.extDOP.VDOP;
373         out.gdop = locationExtended.extDOP.GDOP;
374         out.tdop = locationExtended.extDOP.TDOP;
375     } else if (GPS_LOCATION_EXTENDED_HAS_DOP & locationExtended.flags) {
376         out.flags |= GNSS_LOCATION_INFO_DOP_BIT;
377         out.pdop = locationExtended.pdop;
378         out.hdop = locationExtended.hdop;
379         out.vdop = locationExtended.vdop;
380     }
381     if (GPS_LOCATION_EXTENDED_HAS_MAG_DEV & locationExtended.flags) {
382         out.flags |= GNSS_LOCATION_INFO_MAGNETIC_DEVIATION_BIT;
383         out.magneticDeviation = locationExtended.magneticDeviation;
384     }
385     if (GPS_LOCATION_EXTENDED_HAS_HOR_RELIABILITY & locationExtended.flags) {
386         out.flags |= GNSS_LOCATION_INFO_HOR_RELIABILITY_BIT;
387         switch (locationExtended.horizontal_reliability) {
388             case LOC_RELIABILITY_VERY_LOW:
389                 out.horReliability = LOCATION_RELIABILITY_VERY_LOW;
390                 break;
391             case LOC_RELIABILITY_LOW:
392                 out.horReliability = LOCATION_RELIABILITY_LOW;
393                 break;
394             case LOC_RELIABILITY_MEDIUM:
395                 out.horReliability = LOCATION_RELIABILITY_MEDIUM;
396                 break;
397             case LOC_RELIABILITY_HIGH:
398                 out.horReliability = LOCATION_RELIABILITY_HIGH;
399                 break;
400             default:
401                 out.horReliability = LOCATION_RELIABILITY_NOT_SET;
402                 break;
403         }
404     }
405     if (GPS_LOCATION_EXTENDED_HAS_VERT_RELIABILITY & locationExtended.flags) {
406         out.flags |= GNSS_LOCATION_INFO_VER_RELIABILITY_BIT;
407         switch (locationExtended.vertical_reliability) {
408             case LOC_RELIABILITY_VERY_LOW:
409                 out.verReliability = LOCATION_RELIABILITY_VERY_LOW;
410                 break;
411             case LOC_RELIABILITY_LOW:
412                 out.verReliability = LOCATION_RELIABILITY_LOW;
413                 break;
414             case LOC_RELIABILITY_MEDIUM:
415                 out.verReliability = LOCATION_RELIABILITY_MEDIUM;
416                 break;
417             case LOC_RELIABILITY_HIGH:
418                 out.verReliability = LOCATION_RELIABILITY_HIGH;
419                 break;
420             default:
421                 out.verReliability = LOCATION_RELIABILITY_NOT_SET;
422                 break;
423         }
424     }
425     if (GPS_LOCATION_EXTENDED_HAS_HOR_ELIP_UNC_MAJOR & locationExtended.flags) {
426         out.flags |= GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_SEMI_MAJOR_BIT;
427         out.horUncEllipseSemiMajor = locationExtended.horUncEllipseSemiMajor;
428     }
429     if (GPS_LOCATION_EXTENDED_HAS_HOR_ELIP_UNC_MINOR & locationExtended.flags) {
430         out.flags |= GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_SEMI_MINOR_BIT;
431         out.horUncEllipseSemiMinor = locationExtended.horUncEllipseSemiMinor;
432     }
433     if (GPS_LOCATION_EXTENDED_HAS_HOR_ELIP_UNC_AZIMUTH & locationExtended.flags) {
434         out.flags |= GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_AZIMUTH_BIT;
435         out.horUncEllipseOrientAzimuth = locationExtended.horUncEllipseOrientAzimuth;
436     }
437     if (GPS_LOCATION_EXTENDED_HAS_NORTH_STD_DEV & locationExtended.flags) {
438         out.flags |= GNSS_LOCATION_INFO_NORTH_STD_DEV_BIT;
439         out.northStdDeviation = locationExtended.northStdDeviation;
440     }
441     if (GPS_LOCATION_EXTENDED_HAS_EAST_STD_DEV & locationExtended.flags) {
442         out.flags |= GNSS_LOCATION_INFO_EAST_STD_DEV_BIT;
443         out.eastStdDeviation = locationExtended.eastStdDeviation;
444     }
445     if (GPS_LOCATION_EXTENDED_HAS_NORTH_VEL & locationExtended.flags) {
446         out.flags |= GNSS_LOCATION_INFO_NORTH_VEL_BIT;
447         out.northVelocity = locationExtended.northVelocity;
448     }
449     if (GPS_LOCATION_EXTENDED_HAS_NORTH_VEL_UNC & locationExtended.flags) {
450         out.flags |= GNSS_LOCATION_INFO_NORTH_VEL_UNC_BIT;
451         out.northVelocityStdDeviation = locationExtended.northVelocityStdDeviation;
452     }
453     if (GPS_LOCATION_EXTENDED_HAS_EAST_VEL & locationExtended.flags) {
454         out.flags |= GNSS_LOCATION_INFO_EAST_VEL_BIT;
455         out.eastVelocity = locationExtended.eastVelocity;
456     }
457     if (GPS_LOCATION_EXTENDED_HAS_EAST_VEL_UNC & locationExtended.flags) {
458         out.flags |= GNSS_LOCATION_INFO_EAST_VEL_UNC_BIT;
459         out.eastVelocityStdDeviation = locationExtended.eastVelocityStdDeviation;
460     }
461     if (GPS_LOCATION_EXTENDED_HAS_UP_VEL & locationExtended.flags) {
462         out.flags |= GNSS_LOCATION_INFO_UP_VEL_BIT;
463         out.upVelocity = locationExtended.upVelocity;
464     }
465     if (GPS_LOCATION_EXTENDED_HAS_UP_VEL_UNC & locationExtended.flags) {
466         out.flags |= GNSS_LOCATION_INFO_UP_VEL_UNC_BIT;
467         out.upVelocityStdDeviation = locationExtended.upVelocityStdDeviation;
468     }
469     if (GPS_LOCATION_EXTENDED_HAS_GNSS_SV_USED_DATA & locationExtended.flags) {
470         out.flags |= GNSS_LOCATION_INFO_GNSS_SV_USED_DATA_BIT;
471         out.svUsedInPosition.gpsSvUsedIdsMask =
472                 locationExtended.gnss_sv_used_ids.gps_sv_used_ids_mask;
473         out.svUsedInPosition.gloSvUsedIdsMask =
474                 locationExtended.gnss_sv_used_ids.glo_sv_used_ids_mask;
475         out.svUsedInPosition.galSvUsedIdsMask =
476                 locationExtended.gnss_sv_used_ids.gal_sv_used_ids_mask;
477         out.svUsedInPosition.bdsSvUsedIdsMask =
478                 locationExtended.gnss_sv_used_ids.bds_sv_used_ids_mask;
479         out.svUsedInPosition.qzssSvUsedIdsMask =
480                 locationExtended.gnss_sv_used_ids.qzss_sv_used_ids_mask;
481         out.svUsedInPosition.navicSvUsedIdsMask =
482                 locationExtended.gnss_sv_used_ids.navic_sv_used_ids_mask;
483 
484         out.flags |= GNSS_LOCATION_INFO_NUM_SV_USED_IN_POSITION_BIT;
485         out.numSvUsedInPosition = getNumSvUsed(out.svUsedInPosition.gpsSvUsedIdsMask,
486                                                GPS_SV_PRN_MAX - GPS_SV_PRN_MIN + 1);
487         out.numSvUsedInPosition += getNumSvUsed(out.svUsedInPosition.gloSvUsedIdsMask,
488                                                 GLO_SV_PRN_MAX - GLO_SV_PRN_MIN + 1);
489         out.numSvUsedInPosition += getNumSvUsed(out.svUsedInPosition.qzssSvUsedIdsMask,
490                                                 QZSS_SV_PRN_MAX - QZSS_SV_PRN_MIN + 1);
491         out.numSvUsedInPosition += getNumSvUsed(out.svUsedInPosition.bdsSvUsedIdsMask,
492                                                 BDS_SV_PRN_MAX - BDS_SV_PRN_MIN + 1);
493         out.numSvUsedInPosition += getNumSvUsed(out.svUsedInPosition.galSvUsedIdsMask,
494                                                 GAL_SV_PRN_MAX - GAL_SV_PRN_MIN + 1);
495         out.numSvUsedInPosition += getNumSvUsed(out.svUsedInPosition.navicSvUsedIdsMask,
496                                                 NAVIC_SV_PRN_MAX - NAVIC_SV_PRN_MIN + 1);
497 
498         out.numOfMeasReceived = locationExtended.numOfMeasReceived;
499         for (int idx =0; idx < locationExtended.numOfMeasReceived; idx++) {
500             out.measUsageInfo[idx].gnssSignalType =
501                     locationExtended.measUsageInfo[idx].gnssSignalType;
502             out.measUsageInfo[idx].gnssSvId =
503                     locationExtended.measUsageInfo[idx].gnssSvId;
504             out.measUsageInfo[idx].gnssConstellation =
505                     locationExtended.measUsageInfo[idx].gnssConstellation;
506         }
507     }
508     if (GPS_LOCATION_EXTENDED_HAS_NAV_SOLUTION_MASK & locationExtended.flags) {
509         out.flags |= GNSS_LOCATION_INFO_NAV_SOLUTION_MASK_BIT;
510         out.navSolutionMask = locationExtended.navSolutionMask;
511     }
512     if (GPS_LOCATION_EXTENDED_HAS_POS_DYNAMICS_DATA & locationExtended.flags) {
513         out.flags |= GPS_LOCATION_EXTENDED_HAS_POS_DYNAMICS_DATA;
514         if (locationExtended.bodyFrameData.bodyFrameDataMask &
515                 LOCATION_NAV_DATA_HAS_LONG_ACCEL_BIT) {
516             out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_LONG_ACCEL_BIT;
517         }
518         if (locationExtended.bodyFrameData.bodyFrameDataMask &
519                 LOCATION_NAV_DATA_HAS_LAT_ACCEL_BIT) {
520             out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_LAT_ACCEL_BIT;
521         }
522         if (locationExtended.bodyFrameData.bodyFrameDataMask &
523                 LOCATION_NAV_DATA_HAS_VERT_ACCEL_BIT) {
524             out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_VERT_ACCEL_BIT;
525         }
526         if (locationExtended.bodyFrameData.bodyFrameDataMask &
527                 LOCATION_NAV_DATA_HAS_YAW_RATE_BIT) {
528             out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_YAW_RATE_BIT;
529         }
530         if (locationExtended.bodyFrameData.bodyFrameDataMask &
531             LOCATION_NAV_DATA_HAS_PITCH_BIT) {
532             out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_PITCH_BIT;
533         }
534 
535         if (locationExtended.bodyFrameData.bodyFrameDataMask &
536                 LOCATION_NAV_DATA_HAS_LONG_ACCEL_UNC_BIT) {
537             out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_LONG_ACCEL_UNC_BIT;
538         }
539         if (locationExtended.bodyFrameData.bodyFrameDataMask &
540                 LOCATION_NAV_DATA_HAS_LAT_ACCEL_UNC_BIT) {
541             out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_LAT_ACCEL_UNC_BIT;
542         }
543         if (locationExtended.bodyFrameData.bodyFrameDataMask &
544                 LOCATION_NAV_DATA_HAS_VERT_ACCEL_UNC_BIT) {
545             out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_VERT_ACCEL_UNC_BIT;
546         }
547         if (locationExtended.bodyFrameData.bodyFrameDataMask &
548                 LOCATION_NAV_DATA_HAS_YAW_RATE_UNC_BIT) {
549             out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_YAW_RATE_UNC_BIT;
550         }
551         if (locationExtended.bodyFrameData.bodyFrameDataMask &
552                 LOCATION_NAV_DATA_HAS_PITCH_UNC_BIT) {
553             out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_PITCH_UNC_BIT;
554         }
555 
556         if (locationExtended.bodyFrameDataExt.bodyFrameDataMask &
557                 LOCATION_NAV_DATA_HAS_PITCH_RATE_BIT) {
558             out.bodyFrameDataExt.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_PITCH_RATE_BIT;
559         }
560         if (locationExtended.bodyFrameDataExt.bodyFrameDataMask &
561                 LOCATION_NAV_DATA_HAS_PITCH_RATE_UNC_BIT) {
562             out.bodyFrameDataExt.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_PITCH_RATE_UNC_BIT;
563         }
564         if (locationExtended.bodyFrameDataExt.bodyFrameDataMask &
565                 LOCATION_NAV_DATA_HAS_ROLL_BIT) {
566             out.bodyFrameDataExt.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_ROLL_BIT;
567         }
568         if (locationExtended.bodyFrameDataExt.bodyFrameDataMask &
569                 LOCATION_NAV_DATA_HAS_ROLL_UNC_BIT) {
570             out.bodyFrameDataExt.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_ROLL_UNC_BIT;
571         }
572         if (locationExtended.bodyFrameDataExt.bodyFrameDataMask &
573                 LOCATION_NAV_DATA_HAS_ROLL_RATE_BIT) {
574             out.bodyFrameDataExt.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_ROLL_RATE_BIT;
575         }
576         if (locationExtended.bodyFrameDataExt.bodyFrameDataMask &
577                 LOCATION_NAV_DATA_HAS_ROLL_RATE_UNC_BIT) {
578             out.bodyFrameDataExt.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_ROLL_RATE_UNC_BIT;
579         }
580         if (locationExtended.bodyFrameDataExt.bodyFrameDataMask &
581                 LOCATION_NAV_DATA_HAS_YAW_BIT) {
582             out.bodyFrameDataExt.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_YAW_BIT;
583         }
584         if (locationExtended.bodyFrameDataExt.bodyFrameDataMask &
585                 LOCATION_NAV_DATA_HAS_YAW_UNC_BIT) {
586             out.bodyFrameDataExt.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_YAW_UNC_BIT;
587         }
588 
589         out.bodyFrameData.longAccel = locationExtended.bodyFrameData.longAccel;
590         out.bodyFrameData.latAccel = locationExtended.bodyFrameData.latAccel;
591         out.bodyFrameData.vertAccel = locationExtended.bodyFrameData.vertAccel;
592         out.bodyFrameData.yawRate = locationExtended.bodyFrameData.yawRate;
593         out.bodyFrameData.pitch = locationExtended.bodyFrameData.pitch;
594         out.bodyFrameData.longAccelUnc = locationExtended.bodyFrameData.longAccelUnc;
595         out.bodyFrameData.latAccelUnc  = locationExtended.bodyFrameData.latAccelUnc;
596         out.bodyFrameData.vertAccelUnc = locationExtended.bodyFrameData.vertAccelUnc;
597         out.bodyFrameData.yawRateUnc   = locationExtended.bodyFrameData.yawRateUnc;
598         out.bodyFrameData.pitchUnc     = locationExtended.bodyFrameData.pitchUnc;
599 
600         out.bodyFrameDataExt.pitchRate    = locationExtended.bodyFrameDataExt.pitchRate;
601         out.bodyFrameDataExt.pitchRateUnc = locationExtended.bodyFrameDataExt.pitchRateUnc;
602         out.bodyFrameDataExt.roll         = locationExtended.bodyFrameDataExt.roll;
603         out.bodyFrameDataExt.rollUnc      = locationExtended.bodyFrameDataExt.rollUnc;
604         out.bodyFrameDataExt.rollRate     = locationExtended.bodyFrameDataExt.rollRate;
605         out.bodyFrameDataExt.rollRateUnc  = locationExtended.bodyFrameDataExt.rollRateUnc;
606         out.bodyFrameDataExt.yaw          = locationExtended.bodyFrameDataExt.yaw;
607         out.bodyFrameDataExt.yawUnc       = locationExtended.bodyFrameDataExt.yawUnc;
608     }
609 
610     // Validity of this structure is established from the timeSrc of the GnssSystemTime structure.
611     out.gnssSystemTime = locationExtended.gnssSystemTime;
612 
613     if (GPS_LOCATION_EXTENDED_HAS_LEAP_SECONDS & locationExtended.flags) {
614         out.flags |= GNSS_LOCATION_INFO_LEAP_SECONDS_BIT;
615         out.leapSeconds = locationExtended.leapSeconds;
616     }
617 
618     if (GPS_LOCATION_EXTENDED_HAS_TIME_UNC & locationExtended.flags) {
619         out.flags |= GNSS_LOCATION_INFO_TIME_UNC_BIT;
620         out.timeUncMs = locationExtended.timeUncMs;
621     }
622 
623     if (GPS_LOCATION_EXTENDED_HAS_CALIBRATION_CONFIDENCE & locationExtended.flags) {
624         out.flags |= GNSS_LOCATION_INFO_CALIBRATION_CONFIDENCE_BIT;
625         out.calibrationConfidence = locationExtended.calibrationConfidence;
626     }
627 
628     if (GPS_LOCATION_EXTENDED_HAS_CALIBRATION_STATUS & locationExtended.flags) {
629         out.flags |= GNSS_LOCATION_INFO_CALIBRATION_STATUS_BIT;
630         out.calibrationStatus = locationExtended.calibrationStatus;
631     }
632 
633     if (GPS_LOCATION_EXTENDED_HAS_OUTPUT_ENG_TYPE & locationExtended.flags) {
634         out.flags |= GNSS_LOCATION_INFO_OUTPUT_ENG_TYPE_BIT;
635         out.locOutputEngType = locationExtended.locOutputEngType;
636     }
637 
638     if (GPS_LOCATION_EXTENDED_HAS_OUTPUT_ENG_MASK & locationExtended.flags) {
639         out.flags |= GNSS_LOCATION_INFO_OUTPUT_ENG_MASK_BIT;
640         out.locOutputEngMask = locationExtended.locOutputEngMask;
641     }
642 
643     if (GPS_LOCATION_EXTENDED_HAS_CONFORMITY_INDEX & locationExtended.flags) {
644         out.flags |= GNSS_LOCATION_INFO_CONFORMITY_INDEX_BIT;
645         out.conformityIndex = locationExtended.conformityIndex;
646     }
647 
648     if (GPS_LOCATION_EXTENDED_HAS_LLA_VRP_BASED & locationExtended.flags) {
649         out.flags |= GNSS_LOCATION_INFO_LLA_VRP_BASED_BIT;
650         out.llaVRPBased = locationExtended.llaVRPBased;
651     }
652 
653     if (GPS_LOCATION_EXTENDED_HAS_ENU_VELOCITY_LLA_VRP_BASED & locationExtended.flags) {
654         out.flags |= GNSS_LOCATION_INFO_ENU_VELOCITY_VRP_BASED_BIT;
655         // copy over east, north and up vrp based velocity
656         out.enuVelocityVRPBased[0] = locationExtended.enuVelocityVRPBased[0];
657         out.enuVelocityVRPBased[1] = locationExtended.enuVelocityVRPBased[1];
658         out.enuVelocityVRPBased[2] = locationExtended.enuVelocityVRPBased[2];
659     }
660 
661     if (GPS_LOCATION_EXTENDED_HAS_DR_SOLUTION_STATUS_MASK & locationExtended.flags) {
662         out.flags |= GNSS_LOCATION_INFO_DR_SOLUTION_STATUS_MASK_BIT;
663         out.drSolutionStatusMask = locationExtended.drSolutionStatusMask;
664     }
665 
666     if (GPS_LOCATION_EXTENDED_HAS_ALTITUDE_ASSUMED & locationExtended.flags) {
667         out.flags |= GNSS_LOCATION_INFO_ALTITUDE_ASSUMED_BIT;
668         out.altitudeAssumed = locationExtended.altitudeAssumed;
669     }
670 
671     out.flags |= GNSS_LOCATION_INFO_SESSION_STATUS_BIT;
672     out.sessionStatus = status;
673 }
674 
675 inline uint32_t
convertSuplVersion(const GnssConfigSuplVersion suplVersion)676 GnssAdapter::convertSuplVersion(const GnssConfigSuplVersion suplVersion)
677 {
678     switch (suplVersion) {
679         case GNSS_CONFIG_SUPL_VERSION_2_0_4:
680             return 0x00020004;
681         case GNSS_CONFIG_SUPL_VERSION_2_0_0:
682             return 0x00020000;
683         case GNSS_CONFIG_SUPL_VERSION_2_0_2:
684             return 0x00020002;
685         case GNSS_CONFIG_SUPL_VERSION_1_0_0:
686         default:
687             return 0x00010000;
688     }
689 }
690 
691 uint32_t
convertLppeCp(const GnssConfigLppeControlPlaneMask lppeControlPlaneMask)692 GnssAdapter::convertLppeCp(const GnssConfigLppeControlPlaneMask lppeControlPlaneMask)
693 {
694     uint32_t mask = 0;
695     if (GNSS_CONFIG_LPPE_CONTROL_PLANE_DBH_BIT & lppeControlPlaneMask) {
696         mask |= (1<<0);
697     }
698     if (GNSS_CONFIG_LPPE_CONTROL_PLANE_WLAN_AP_MEASUREMENTS_BIT & lppeControlPlaneMask) {
699         mask |= (1<<1);
700     }
701     if (GNSS_CONFIG_LPPE_CONTROL_PLANE_SRN_AP_MEASUREMENTS_BIT & lppeControlPlaneMask) {
702         mask |= (1<<2);
703     }
704     if (GNSS_CONFIG_LPPE_CONTROL_PLANE_SENSOR_BARO_MEASUREMENTS_BIT & lppeControlPlaneMask) {
705         mask |= (1<<3);
706     }
707     return mask;
708 }
709 
710 uint32_t
convertLppeUp(const GnssConfigLppeUserPlaneMask lppeUserPlaneMask)711 GnssAdapter::convertLppeUp(const GnssConfigLppeUserPlaneMask lppeUserPlaneMask)
712 {
713     uint32_t mask = 0;
714     if (GNSS_CONFIG_LPPE_USER_PLANE_DBH_BIT & lppeUserPlaneMask) {
715         mask |= (1<<0);
716     }
717     if (GNSS_CONFIG_LPPE_USER_PLANE_WLAN_AP_MEASUREMENTS_BIT & lppeUserPlaneMask) {
718         mask |= (1<<1);
719     }
720     if (GNSS_CONFIG_LPPE_USER_PLANE_SRN_AP_MEASUREMENTS_BIT & lppeUserPlaneMask) {
721         mask |= (1<<2);
722     }
723     if (GNSS_CONFIG_LPPE_USER_PLANE_SENSOR_BARO_MEASUREMENTS_BIT & lppeUserPlaneMask) {
724         mask |= (1<<3);
725     }
726     return mask;
727 }
728 
729 uint32_t
convertAGloProt(const GnssConfigAGlonassPositionProtocolMask aGloPositionProtocolMask)730 GnssAdapter::convertAGloProt(const GnssConfigAGlonassPositionProtocolMask aGloPositionProtocolMask)
731 {
732     uint32_t mask = 0;
733     if (GNSS_CONFIG_RRC_CONTROL_PLANE_BIT & aGloPositionProtocolMask) {
734         mask |= (1<<0);
735     }
736     if (GNSS_CONFIG_RRLP_USER_PLANE_BIT & aGloPositionProtocolMask) {
737         mask |= (1<<1);
738     }
739     if (GNSS_CONFIG_LLP_USER_PLANE_BIT & aGloPositionProtocolMask) {
740         mask |= (1<<2);
741     }
742     if (GNSS_CONFIG_LLP_CONTROL_PLANE_BIT & aGloPositionProtocolMask) {
743         mask |= (1<<3);
744     }
745     return mask;
746 }
747 
748 uint32_t
convertEP4ES(const GnssConfigEmergencyPdnForEmergencySupl emergencyPdnForEmergencySupl)749 GnssAdapter::convertEP4ES(const GnssConfigEmergencyPdnForEmergencySupl emergencyPdnForEmergencySupl)
750 {
751     switch (emergencyPdnForEmergencySupl) {
752        case GNSS_CONFIG_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_YES:
753            return 1;
754        case GNSS_CONFIG_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_NO:
755        default:
756            return 0;
757     }
758 }
759 
760 uint32_t
convertSuplEs(const GnssConfigSuplEmergencyServices suplEmergencyServices)761 GnssAdapter::convertSuplEs(const GnssConfigSuplEmergencyServices suplEmergencyServices)
762 {
763     switch (suplEmergencyServices) {
764        case GNSS_CONFIG_SUPL_EMERGENCY_SERVICES_YES:
765            return 1;
766        case GNSS_CONFIG_SUPL_EMERGENCY_SERVICES_NO:
767        default:
768            return 0;
769     }
770 }
771 
772 uint32_t
convertSuplMode(const GnssConfigSuplModeMask suplModeMask)773 GnssAdapter::convertSuplMode(const GnssConfigSuplModeMask suplModeMask)
774 {
775     uint32_t mask = 0;
776     if (GNSS_CONFIG_SUPL_MODE_MSB_BIT & suplModeMask) {
777         mask |= (1<<0);
778     }
779     if (GNSS_CONFIG_SUPL_MODE_MSA_BIT & suplModeMask) {
780         mask |= (1<<1);
781     }
782     return mask;
783 }
784 
785 void
readConfigCommand()786 GnssAdapter::readConfigCommand()
787 {
788     LOC_LOGD("%s]: ", __func__);
789 
790     struct MsgReadConfig : public LocMsg {
791         GnssAdapter* mAdapter;
792         ContextBase& mContext;
793         inline MsgReadConfig(GnssAdapter* adapter,
794                              ContextBase& context) :
795             LocMsg(),
796             mAdapter(adapter),
797             mContext(context) {}
798         inline virtual void proc() const {
799             static bool confReadDone = false;
800             if (!confReadDone) {
801                 confReadDone = true;
802                 // reads config into mContext->mGps_conf
803                 mContext.readConfig();
804 
805                 uint32_t allowFlpNetworkFixes = 0;
806                 static const loc_param_s_type flp_conf_param_table[] =
807                 {
808                     {"ALLOW_NETWORK_FIXES", &allowFlpNetworkFixes, NULL, 'n'},
809                 };
810                 UTIL_READ_CONF(LOC_PATH_FLP_CONF, flp_conf_param_table);
811                 LOC_LOGd("allowFlpNetworkFixes %u", allowFlpNetworkFixes);
812                 mAdapter->setAllowFlpNetworkFixes(allowFlpNetworkFixes);
813             }
814         }
815     };
816 
817     if (mContext != NULL) {
818         sendMsg(new MsgReadConfig(this, *mContext));
819     }
820 }
821 
822 void
setSuplHostServer(const char * server,int port,LocServerType type)823 GnssAdapter::setSuplHostServer(const char* server, int port, LocServerType type)
824 {
825     if (ContextBase::mGps_conf.AGPS_CONFIG_INJECT) {
826         char serverUrl[MAX_URL_LEN] = {};
827         int32_t length = -1;
828         const char noHost[] = "NONE";
829 
830         if ((NULL == server) || (server[0] == 0) ||
831                 (strncasecmp(noHost, server, sizeof(noHost)) == 0)) {
832             serverUrl[0] = '\0';
833             length = 0;
834         } else if (port > 0) {
835             length = snprintf(serverUrl, sizeof(serverUrl), "%s:%u", server, port);
836         }
837         if (LOC_AGPS_SUPL_SERVER != type && LOC_AGPS_MO_SUPL_SERVER != type) {
838             LOC_LOGe("Invalid type=%d", type);
839         } else if (length >= 0) {
840             if (LOC_AGPS_SUPL_SERVER == type) {
841                 getServerUrl().assign(serverUrl);
842                 strlcpy(ContextBase::mGps_conf.SUPL_HOST,
843                         (nullptr == server) ? serverUrl : server,
844                         LOC_MAX_PARAM_STRING);
845                 ContextBase::mGps_conf.SUPL_PORT = port;
846             } else {
847                 if (strncasecmp(getMoServerUrl().c_str(), serverUrl, sizeof(serverUrl)) != 0) {
848                     getMoServerUrl().assign(serverUrl);
849                 }
850             }
851         }
852     }
853 }
854 
855 void
setConfig()856 GnssAdapter::setConfig()
857 {
858     LOC_LOGD("%s]: ", __func__);
859 
860     // set nmea mask type
861     uint32_t mask = 0;
862     if (NMEA_PROVIDER_MP == ContextBase::mGps_conf.NMEA_PROVIDER) {
863         mask |= LOC_NMEA_ALL_GENERAL_SUPPORTED_MASK;
864         if (ContextBase::mGps_conf.NMEA_TAG_BLOCK_GROUPING_ENABLED) {
865             mask |= LOC_NMEA_MASK_TAGBLOCK_V02;
866         }
867     }
868     if (ContextBase::isFeatureSupported(LOC_SUPPORTED_FEATURE_DEBUG_NMEA_V02)) {
869         mask |= LOC_NMEA_MASK_DEBUG_V02;
870     }
871     if (mNmeaMask != mask) {
872         mNmeaMask = mask;
873         if (mNmeaMask) {
874             for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
875                 if ((it->second.gnssNmeaCb != nullptr)) {
876                     updateEvtMask(LOC_API_ADAPTER_BIT_NMEA_1HZ_REPORT,
877                                   LOC_REGISTRATION_MASK_ENABLED);
878                     break;
879                 }
880             }
881         }
882     }
883 
884     std::string oldMoServerUrl = getMoServerUrl();
885     setSuplHostServer(ContextBase::mGps_conf.SUPL_HOST,
886                       ContextBase::mGps_conf.SUPL_PORT,
887                       LOC_AGPS_SUPL_SERVER);
888     setSuplHostServer(ContextBase::mGps_conf.MO_SUPL_HOST,
889                       ContextBase::mGps_conf.MO_SUPL_PORT,
890                       LOC_AGPS_MO_SUPL_SERVER);
891 
892     // inject the configurations into modem
893     loc_gps_cfg_s gpsConf = ContextBase::mGps_conf;
894     loc_sap_cfg_s_type sapConf = ContextBase::mSap_conf;
895 
896     //cache the injected configuration with GnssConfigRequested struct
897     GnssConfig gnssConfigRequested = {};
898     gnssConfigRequested.flags |= GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT |
899             GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT;
900     /* Here we process an SSR. We need to set the GPS_LOCK to the proper values, as follows:
901     1. Q behavior. This is identified by mSupportNfwControl being 1. In this case
902     ContextBase::mGps_conf.GPS_LOCK is a "state", meaning it should reflect the
903     NV value. Therefore we will set the NV to ContextBase::mGps_conf.GPS_LOCK
904     2. P behavior. This is identified by mSupportNfwControl being 0. In this case
905     ContextBase::mGps_conf.GPS_LOCK is a "configuration", meaning it should hold
906     the "mask" for NI. There are two subcases:
907     a. Location enabled in GUI (1 == getAfwControlId()). We need to set
908     the NV to GNSS_CONFIG_GPS_LOCK_NONE (both MO and NI enabled)
909     b. Location disabled in GUI (0 == getAfwControlId()). We need to set
910     the NV to ContextBase::mGps_conf.GPS_LOCK (the "mask", which is SIM-card
911     specific)
912     */
913     if (mSupportNfwControl || (0 == getAfwControlId())) {
914         gnssConfigRequested.gpsLock = gpsConf.GPS_LOCK;
915     } else {
916         gnssConfigRequested.gpsLock = GNSS_CONFIG_GPS_LOCK_NONE;
917     }
918     gnssConfigRequested.flags |= GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT |
919             GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT |
920             GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT |
921             GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT;
922     gnssConfigRequested.suplVersion = mLocApi->convertSuplVersion(gpsConf.SUPL_VER);
923     gnssConfigRequested.lppProfileMask = gpsConf.LPP_PROFILE;
924     gnssConfigRequested.aGlonassPositionProtocolMask = gpsConf.A_GLONASS_POS_PROTOCOL_SELECT;
925     if (gpsConf.LPPE_CP_TECHNOLOGY) {
926         gnssConfigRequested.flags |= GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT;
927         gnssConfigRequested.lppeControlPlaneMask =
928                 mLocApi->convertLppeCp(gpsConf.LPPE_CP_TECHNOLOGY);
929     }
930 
931     if (gpsConf.LPPE_UP_TECHNOLOGY) {
932         gnssConfigRequested.flags |= GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT;
933         gnssConfigRequested.lppeUserPlaneMask =
934                 mLocApi->convertLppeUp(gpsConf.LPPE_UP_TECHNOLOGY);
935     }
936     gnssConfigRequested.blacklistedSvIds.assign(mBlacklistedSvIds.begin(),
937                                                 mBlacklistedSvIds.end());
938     mLocApi->sendMsg(new LocApiMsg(
939             [this, gpsConf, sapConf, oldMoServerUrl, gnssConfigRequested] () mutable {
940         gnssUpdateConfig(oldMoServerUrl, gnssConfigRequested, gnssConfigRequested);
941 
942         // set nmea mask type
943         uint32_t mask = 0;
944         if (NMEA_PROVIDER_MP == gpsConf.NMEA_PROVIDER) {
945             mask |= LOC_NMEA_ALL_GENERAL_SUPPORTED_MASK;
946             if (gpsConf.NMEA_TAG_BLOCK_GROUPING_ENABLED) {
947                 mask |= LOC_NMEA_MASK_TAGBLOCK_V02;
948             }
949         }
950         if (ContextBase::isFeatureSupported(LOC_SUPPORTED_FEATURE_DEBUG_NMEA_V02)) {
951             mask |= LOC_NMEA_MASK_DEBUG_V02;
952         }
953 
954         if (mask != 0) {
955             mLocApi->setNMEATypesSync(mask);
956         }
957 
958         // load tunc configuration from config file on first boot-up,
959         // e.g.: adapter.mLocConfigInfo.tuncConfigInfo.isValid is false
960         if (mLocConfigInfo.tuncConfigInfo.isValid == false) {
961             mLocConfigInfo.tuncConfigInfo.isValid = true;
962             mLocConfigInfo.tuncConfigInfo.enable =
963                     (gpsConf.CONSTRAINED_TIME_UNCERTAINTY_ENABLED == 1);
964             mLocConfigInfo.tuncConfigInfo.tuncThresholdMs =
965                    (float)gpsConf.CONSTRAINED_TIME_UNCERTAINTY_THRESHOLD;
966             mLocConfigInfo.tuncConfigInfo.energyBudget =
967                    gpsConf.CONSTRAINED_TIME_UNCERTAINTY_ENERGY_BUDGET;
968         }
969 
970         mLocApi->setConstrainedTuncMode(
971                 mLocConfigInfo.tuncConfigInfo.enable,
972                 mLocConfigInfo.tuncConfigInfo.tuncThresholdMs,
973                 mLocConfigInfo.tuncConfigInfo.energyBudget);
974 
975         // load pace configuration from config file on first boot-up,
976         // e.g.: adapter.mLocConfigInfo.paceConfigInfo.isValid is false
977         if (mLocConfigInfo.paceConfigInfo.isValid == false) {
978             mLocConfigInfo.paceConfigInfo.isValid = true;
979             mLocConfigInfo.paceConfigInfo.enable =
980                     (gpsConf.POSITION_ASSISTED_CLOCK_ESTIMATOR_ENABLED==1);
981         }
982         mLocApi->setPositionAssistedClockEstimatorMode(
983                 mLocConfigInfo.paceConfigInfo.enable);
984 
985         // we do not support control robust location from gps.conf
986         if (mLocConfigInfo.robustLocationConfigInfo.isValid == true) {
987             mLocApi->configRobustLocation(
988                     mLocConfigInfo.robustLocationConfigInfo.enable,
989                     mLocConfigInfo.robustLocationConfigInfo.enableFor911);
990         }
991 
992         if (sapConf.GYRO_BIAS_RANDOM_WALK_VALID ||
993             sapConf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY_VALID ||
994             sapConf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY_VALID ||
995             sapConf.RATE_RANDOM_WALK_SPECTRAL_DENSITY_VALID ||
996             sapConf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY_VALID ) {
997             mLocApi->setSensorPropertiesSync(
998                 sapConf.GYRO_BIAS_RANDOM_WALK_VALID,
999                 sapConf.GYRO_BIAS_RANDOM_WALK,
1000                 sapConf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY_VALID,
1001                 sapConf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY,
1002                 sapConf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY_VALID,
1003                 sapConf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY,
1004                 sapConf.RATE_RANDOM_WALK_SPECTRAL_DENSITY_VALID,
1005                 sapConf.RATE_RANDOM_WALK_SPECTRAL_DENSITY,
1006                 sapConf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY_VALID,
1007                 sapConf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY);
1008         }
1009         mLocApi->setSensorPerfControlConfigSync(
1010                 sapConf.SENSOR_CONTROL_MODE,
1011                 sapConf.SENSOR_ACCEL_SAMPLES_PER_BATCH,
1012                 sapConf.SENSOR_ACCEL_BATCHES_PER_SEC,
1013                 sapConf.SENSOR_GYRO_SAMPLES_PER_BATCH,
1014                 sapConf.SENSOR_GYRO_BATCHES_PER_SEC,
1015                 sapConf.SENSOR_ACCEL_SAMPLES_PER_BATCH_HIGH,
1016                 sapConf.SENSOR_ACCEL_BATCHES_PER_SEC_HIGH,
1017                 sapConf.SENSOR_GYRO_SAMPLES_PER_BATCH_HIGH,
1018                 sapConf.SENSOR_GYRO_BATCHES_PER_SEC_HIGH,
1019                 sapConf.SENSOR_ALGORITHM_CONFIG_MASK);
1020     } ));
1021     // deal with Measurement Corrections
1022     if (true == mIsMeasCorrInterfaceOpen) {
1023         initMeasCorr(true);
1024     }
1025 }
1026 
gnssUpdateConfig(const std::string & oldMoServerUrl,GnssConfig & gnssConfigRequested,GnssConfig & gnssConfigNeedEngineUpdate,size_t count)1027 std::vector<LocationError> GnssAdapter::gnssUpdateConfig(const std::string& oldMoServerUrl,
1028         GnssConfig& gnssConfigRequested, GnssConfig& gnssConfigNeedEngineUpdate, size_t count) {
1029     loc_gps_cfg_s gpsConf = ContextBase::mGps_conf;
1030     size_t index = 0;
1031     LocationError err = LOCATION_ERROR_SUCCESS;
1032     std::vector<LocationError> errsList = {err};
1033     if (count > 0) {
1034         errsList.insert(errsList.begin(), count, LOCATION_ERROR_SUCCESS);
1035     }
1036 
1037     std::string serverUrl = getServerUrl();
1038     std::string moServerUrl = getMoServerUrl();
1039 
1040     int serverUrlLen = serverUrl.length();
1041     int moServerUrlLen = moServerUrl.length();
1042 
1043     if (!ContextBase::mGps_conf.AGPS_CONFIG_INJECT) {
1044         LOC_LOGd("AGPS_CONFIG_INJECT is 0. Not setting flags for AGPS configurations");
1045         gnssConfigRequested.flags &= ~(GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT |
1046                 GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT |
1047                 GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT |
1048                 GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT);
1049     }
1050 
1051     if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT) {
1052         if (gnssConfigNeedEngineUpdate.flags & GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT) {
1053             err = mLocApi->setGpsLockSync(gnssConfigRequested.gpsLock);
1054             if (index < count) {
1055                 errsList[index] = err;
1056             }
1057         }
1058         index++;
1059     }
1060 
1061     if (gnssConfigRequested.flags &
1062             GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT) {
1063         if (gnssConfigNeedEngineUpdate.flags &
1064                 GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT) {
1065             if (gnssConfigNeedEngineUpdate.assistanceServer.type ==
1066                     GNSS_ASSISTANCE_TYPE_SUPL) {
1067                 err = mLocApi->setServerSync(
1068                         serverUrl.c_str(), serverUrlLen, LOC_AGPS_SUPL_SERVER);
1069                 if (index < count) {
1070                     errsList[index] = err;
1071                 }
1072                 if (0 != oldMoServerUrl.compare(moServerUrl)) {
1073                     LocationError locErr =
1074                         mLocApi->setServerSync(moServerUrl.c_str(),
1075                                 moServerUrlLen,
1076                                 LOC_AGPS_MO_SUPL_SERVER);
1077                     if (locErr != LOCATION_ERROR_SUCCESS) {
1078                         LOC_LOGe("Error while setting MO SUPL_HOST server:%s",
1079                                 moServerUrl.c_str());
1080                     }
1081                 }
1082             } else if (gnssConfigNeedEngineUpdate.assistanceServer.type ==
1083                     GNSS_ASSISTANCE_TYPE_C2K) {
1084                 struct in_addr addr;
1085                 struct hostent* hp;
1086                 bool resolveAddrSuccess = true;
1087 
1088                 hp = gethostbyname(
1089                         gnssConfigNeedEngineUpdate.assistanceServer.hostName);
1090                 if (hp != NULL) { /* DNS OK */
1091                     memcpy(&addr, hp->h_addr_list[0], hp->h_length);
1092                 } else {
1093                     /* Try IP representation */
1094                     if (inet_aton(
1095                                 gnssConfigNeedEngineUpdate.assistanceServer.hostName,
1096                                 &addr) == 0) {
1097                         /* IP not valid */
1098                         LOC_LOGE("%s]: hostname '%s' cannot be resolved ",
1099                                 __func__,
1100                                 gnssConfigNeedEngineUpdate.assistanceServer.hostName);
1101                         if (index < count) {
1102                             errsList[index] = LOCATION_ERROR_INVALID_PARAMETER;
1103                         }
1104                     } else {
1105                         resolveAddrSuccess = false;
1106                     }
1107                 }
1108 
1109                 if (resolveAddrSuccess) {
1110                     unsigned int ip = htonl(addr.s_addr);
1111                     err = mLocApi->setServerSync(ip,
1112                             gnssConfigNeedEngineUpdate.assistanceServer.port,
1113                             LOC_AGPS_CDMA_PDE_SERVER);
1114                     if (index < count) {
1115                         errsList[index] = err;
1116                     }
1117                 }
1118             }
1119         }
1120         index++;
1121     }
1122 
1123     if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT) {
1124         if (gnssConfigNeedEngineUpdate.flags &
1125                 GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT) {
1126             err = mLocApi->setSUPLVersionSync(gnssConfigRequested.suplVersion);
1127             if (index < count) {
1128                 errsList[index] = err;
1129             }
1130         }
1131         index++;
1132     }
1133 
1134     /* Comment out LPP injection as it's configured by MBN.
1135     if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT) {
1136         if (gnssConfigNeedEngineUpdate.flags &
1137                 GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT) {
1138             err = mLocApi->setLPPConfigSync(gnssConfigRequested.lppProfileMask);
1139             if (index < count) {
1140                 errsList[index] = err;
1141             }
1142         }
1143         index++;
1144     }
1145     */
1146 
1147     /* Comment out LPPe injection as it's configured by MBN.
1148     if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT) {
1149         if (gnssConfigNeedEngineUpdate.flags &
1150                 GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT) {
1151             err = mLocApi->setLPPeProtocolCpSync(
1152                     gnssConfigRequested.lppeControlPlaneMask);
1153             if (index < count) {
1154                 errsList[index] = err;
1155             }
1156         }
1157         index++;
1158     }
1159 
1160     if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT) {
1161         if (gnssConfigNeedEngineUpdate.flags &
1162                 GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT) {
1163             err = mLocApi->setLPPeProtocolUpSync(
1164                     gnssConfigRequested.lppeUserPlaneMask);
1165             if (index < count) {
1166                 errsList[index] = err;
1167             }
1168         }
1169         index++;
1170     }
1171     */
1172 
1173     if (gnssConfigRequested.flags &
1174             GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT) {
1175         if (gnssConfigNeedEngineUpdate.flags &
1176                 GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT) {
1177             err = mLocApi->setAGLONASSProtocolSync(
1178                     gnssConfigRequested.aGlonassPositionProtocolMask);
1179             if (index < count) {
1180                 errsList[index] = err;
1181             }
1182         }
1183         index++;
1184     }
1185     if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT) {
1186         // Check if feature is supported
1187         if (!ContextBase::isFeatureSupported(
1188                     LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02)) {
1189             LOC_LOGe("Feature constellation enablement not supported.");
1190             err = LOCATION_ERROR_NOT_SUPPORTED;
1191         } else {
1192             // Send the SV ID Config to Modem
1193             mBlacklistedSvIds.assign(gnssConfigRequested.blacklistedSvIds.begin(),
1194                     gnssConfigRequested.blacklistedSvIds.end());
1195             err = gnssSvIdConfigUpdateSync(gnssConfigRequested.blacklistedSvIds);
1196             if (LOCATION_ERROR_SUCCESS != err) {
1197                 LOC_LOGe("Failed to send config to modem, err %d", err);
1198             }
1199         }
1200         if (index < count) {
1201             errsList[index] = err;
1202         }
1203         index++;
1204     }
1205     if (gnssConfigRequested.flags &
1206             GNSS_CONFIG_FLAGS_EMERGENCY_EXTENSION_SECONDS_BIT) {
1207         if (gnssConfigNeedEngineUpdate.flags &
1208                 GNSS_CONFIG_FLAGS_EMERGENCY_EXTENSION_SECONDS_BIT) {
1209             err = mLocApi->setEmergencyExtensionWindowSync(
1210                     gnssConfigRequested.emergencyExtensionSeconds);
1211             if (index < count) {
1212                 errsList[index] = err;
1213             }
1214         }
1215         index++;
1216     }
1217 
1218     if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_MIN_SV_ELEVATION_BIT) {
1219         GnssConfig gnssConfig = {};
1220         gnssConfig.flags = GNSS_CONFIG_FLAGS_MIN_SV_ELEVATION_BIT;
1221         gnssConfig.minSvElevation = gnssConfigRequested.minSvElevation;
1222         err = mLocApi->setParameterSync(gnssConfig);
1223         if (index < count) {
1224             errsList[index] = err;
1225         }
1226         index++;
1227     }
1228 
1229     return errsList;
1230 }
1231 
1232 uint32_t*
gnssUpdateConfigCommand(const GnssConfig & config)1233 GnssAdapter::gnssUpdateConfigCommand(const GnssConfig& config)
1234 {
1235     // count the number of bits set
1236     GnssConfigFlagsMask flagsCopy = config.flags;
1237     size_t count = 0;
1238     while (flagsCopy > 0) {
1239         if (flagsCopy & 1) {
1240             count++;
1241         }
1242         flagsCopy >>= 1;
1243     }
1244     std::string idsString = "[";
1245     uint32_t* ids = NULL;
1246     if (count > 0) {
1247         ids = new uint32_t[count];
1248         if (ids == nullptr) {
1249             LOC_LOGE("%s] new allocation failed, fatal error.", __func__);
1250             return nullptr;
1251         }
1252         for (size_t i=0; i < count; ++i) {
1253             ids[i] = generateSessionId();
1254             IF_LOC_LOGD {
1255                 idsString += std::to_string(ids[i]) + " ";
1256             }
1257         }
1258     }
1259     idsString += "]";
1260 
1261     LOC_LOGD("%s]: ids %s flags 0x%X", __func__, idsString.c_str(), config.flags);
1262 
1263     struct MsgGnssUpdateConfig : public LocMsg {
1264         GnssAdapter& mAdapter;
1265         LocApiBase& mApi;
1266         GnssConfig mConfig;
1267         size_t mCount;
1268         uint32_t* mIds;
1269         inline MsgGnssUpdateConfig(GnssAdapter& adapter,
1270                                    LocApiBase& api,
1271                                    GnssConfig config,
1272                                    uint32_t* ids,
1273                                    size_t count) :
1274             LocMsg(),
1275             mAdapter(adapter),
1276             mApi(api),
1277             mConfig(config),
1278             mCount(count),
1279             mIds(nullptr) {
1280                 if (mCount > 0) {
1281                     mIds = new uint32_t[count];
1282                     if (mIds) {
1283                         for (uint32_t index = 0; index < count; index++) {
1284                             mIds[index] = ids[index];
1285                         }
1286                     } else {
1287                         LOC_LOGe("memory allocation for mIds failed");
1288                     }
1289                 }
1290         }
1291 
1292         inline MsgGnssUpdateConfig(const MsgGnssUpdateConfig& obj) :
1293                 MsgGnssUpdateConfig(obj.mAdapter, obj.mApi, obj.mConfig,
1294                         obj.mIds, obj.mCount) {}
1295 
1296         inline virtual ~MsgGnssUpdateConfig()
1297         {
1298             if (nullptr != mIds) delete[] mIds;
1299         }
1300 
1301         inline virtual void proc() const {
1302             if (!mAdapter.isEngineCapabilitiesKnown()) {
1303                 mAdapter.mPendingMsgs.push_back(new MsgGnssUpdateConfig(*this));
1304                 return;
1305             }
1306             GnssAdapter& adapter = mAdapter;
1307             size_t countOfConfigs = mCount;
1308             GnssConfig gnssConfigRequested = mConfig;
1309             GnssConfig gnssConfigNeedEngineUpdate = mConfig;
1310 
1311             std::vector<uint32_t> sessionIds;
1312             sessionIds.assign(mIds, mIds + mCount);
1313             std::vector<LocationError> errs(mCount, LOCATION_ERROR_SUCCESS);
1314             int index = 0;
1315             bool needSuspendResume = false;
1316 
1317             if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT) {
1318                 GnssConfigGpsLock newGpsLock = gnssConfigRequested.gpsLock;
1319 
1320                 newGpsLock |= GNSS_CONFIG_GPS_LOCK_MO;
1321                 ContextBase::mGps_conf.GPS_LOCK = newGpsLock;
1322                 /* If we get here it means that the changes in the framework to request for
1323                    'P' behavior were made, and therefore we need to "behave" as in 'P'
1324                 However, we need to determine if enableCommand function has already been
1325                 called, since it could get called before this function.*/
1326                 if (0 != mAdapter.getAfwControlId()) {
1327                     /* enableCommand function has already been called since getAfwControlId
1328                     returns non zero. Now there are two possible cases:
1329                     1. This is the first time this function is called
1330                        (mSupportNfwControl is true). We need to behave as in 'P', but
1331                        for the first time, meaning MO was enabled, but NI was not, so
1332                        we need to unlock NI
1333                     2. This is not the first time this function is called, meaning we
1334                        are already behaving as in 'P'. No need to update the configuration
1335                        in this case (return to 'P' code) */
1336                     if (mAdapter.mSupportNfwControl) {
1337                         // case 1 above
1338                         newGpsLock = GNSS_CONFIG_GPS_LOCK_NONE;
1339                     } else {
1340                         // case 2 above
1341                         gnssConfigNeedEngineUpdate.flags &= ~(GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT);
1342                     }
1343                 }
1344                 gnssConfigRequested.gpsLock = newGpsLock;
1345                 mAdapter.mSupportNfwControl = false;
1346                 index++;
1347             }
1348             if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT) {
1349                 uint32_t newSuplVersion =
1350                         mAdapter.convertSuplVersion(gnssConfigRequested.suplVersion);
1351                 ContextBase::mGps_conf.SUPL_VER = newSuplVersion;
1352                 index++;
1353             }
1354             if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT) {
1355                 if (GNSS_ASSISTANCE_TYPE_SUPL == mConfig.assistanceServer.type) {
1356                     mAdapter.setSuplHostServer(mConfig.assistanceServer.hostName,
1357                                                      mConfig.assistanceServer.port,
1358                                                      LOC_AGPS_SUPL_SERVER);
1359                 } else {
1360                     LOC_LOGE("%s]: Not a valid gnss assistance type %u",
1361                             __func__, mConfig.assistanceServer.type);
1362                     errs.at(index) = LOCATION_ERROR_INVALID_PARAMETER;
1363                     gnssConfigNeedEngineUpdate.flags &=
1364                             ~(GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT);
1365                 }
1366                 index++;
1367             }
1368             if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT) {
1369                 uint32_t newLppProfileMask = gnssConfigRequested.lppProfileMask;
1370                 ContextBase::mGps_conf.LPP_PROFILE = newLppProfileMask;
1371                 index++;
1372             }
1373             if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT) {
1374                 uint32_t newLppeControlPlaneMask =
1375                         mAdapter.convertLppeCp(gnssConfigRequested.lppeControlPlaneMask);
1376                 ContextBase::mGps_conf.LPPE_CP_TECHNOLOGY = newLppeControlPlaneMask;
1377                 index++;
1378             }
1379             if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT) {
1380                 uint32_t newLppeUserPlaneMask =
1381                         mAdapter.convertLppeUp(gnssConfigRequested.lppeUserPlaneMask);
1382                 ContextBase::mGps_conf.LPPE_UP_TECHNOLOGY = newLppeUserPlaneMask;
1383                 index++;
1384             }
1385             if (gnssConfigRequested.flags &
1386                     GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT) {
1387                 uint32_t newAGloProtMask =
1388                         mAdapter.convertAGloProt(gnssConfigRequested.aGlonassPositionProtocolMask);
1389                 ContextBase::mGps_conf.A_GLONASS_POS_PROTOCOL_SELECT = newAGloProtMask;
1390                 index++;
1391             }
1392             if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT) {
1393                 uint32_t newEP4ES = mAdapter.convertEP4ES(
1394                         gnssConfigRequested.emergencyPdnForEmergencySupl);
1395                 if (newEP4ES != ContextBase::mGps_conf.USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL) {
1396                     ContextBase::mGps_conf.USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL = newEP4ES;
1397                 }
1398                 index++;
1399             }
1400             if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT) {
1401                 uint32_t newSuplEs = mAdapter.convertSuplEs(
1402                         gnssConfigRequested.suplEmergencyServices);
1403                 if (newSuplEs != ContextBase::mGps_conf.SUPL_ES) {
1404                     ContextBase::mGps_conf.SUPL_ES = newSuplEs;
1405                 }
1406                 index++;
1407             }
1408             if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_SUPL_MODE_BIT) {
1409                 uint32_t newSuplMode = mAdapter.convertSuplMode(gnssConfigRequested.suplModeMask);
1410                 ContextBase::mGps_conf.SUPL_MODE = newSuplMode;
1411                 mAdapter.broadcastCapabilities(mAdapter.getCapabilities());
1412                 index++;
1413             }
1414 
1415             if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_MIN_SV_ELEVATION_BIT) {
1416                 needSuspendResume = true;
1417                 index++;
1418             }
1419 
1420             if (needSuspendResume == true) {
1421                 mAdapter.suspendSessions();
1422             }
1423             LocApiCollectiveResponse *configCollectiveResponse = new LocApiCollectiveResponse(
1424                     *adapter.getContext(),
1425                     [&adapter, sessionIds, countOfConfigs] (std::vector<LocationError> errs) {
1426 
1427                     std::vector<uint32_t> ids(sessionIds);
1428                     adapter.reportResponse(countOfConfigs, errs.data(), ids.data());
1429             });
1430 
1431             mApi.sendMsg(new LocApiMsg(
1432                     [&adapter, gnssConfigRequested, gnssConfigNeedEngineUpdate,
1433                     countOfConfigs, configCollectiveResponse, errs] () mutable {
1434                 std::vector<LocationError> errsList = adapter.gnssUpdateConfig("",
1435                         gnssConfigRequested, gnssConfigNeedEngineUpdate, countOfConfigs);
1436 
1437                 configCollectiveResponse->returnToSender(errsList);
1438             }));
1439 
1440             if (needSuspendResume == true) {
1441                 mAdapter.restartSessions();
1442             }
1443         }
1444     };
1445 
1446     if (NULL != ids) {
1447         sendMsg(new MsgGnssUpdateConfig(*this, *mLocApi, config, ids, count));
1448     } else {
1449         LOC_LOGE("%s]: No GNSS config items to update", __func__);
1450     }
1451 
1452     return ids;
1453 }
1454 
1455 void
gnssSvIdConfigUpdate(const std::vector<GnssSvIdSource> & blacklistedSvIds)1456 GnssAdapter::gnssSvIdConfigUpdate(const std::vector<GnssSvIdSource>& blacklistedSvIds)
1457 {
1458     // Clear the existing config
1459     memset(&mGnssSvIdConfig, 0, sizeof(GnssSvIdConfig));
1460 
1461     // Convert the sv id lists to masks
1462     bool convertSuccess = convertToGnssSvIdConfig(blacklistedSvIds, mGnssSvIdConfig);
1463 
1464     // Now send to Modem if conversion successful
1465     if (convertSuccess) {
1466         gnssSvIdConfigUpdate();
1467     } else {
1468         LOC_LOGe("convertToGnssSvIdConfig failed");
1469     }
1470 }
1471 
1472 void
gnssSvIdConfigUpdate()1473 GnssAdapter::gnssSvIdConfigUpdate()
1474 {
1475     LOC_LOGd("blacklist bds 0x%" PRIx64 ", glo 0x%" PRIx64
1476             ", qzss 0x%" PRIx64 ", gal 0x%" PRIx64 ", sbas 0x%" PRIx64 ", navic 0x%" PRIx64,
1477             mGnssSvIdConfig.bdsBlacklistSvMask, mGnssSvIdConfig.gloBlacklistSvMask,
1478             mGnssSvIdConfig.qzssBlacklistSvMask, mGnssSvIdConfig.galBlacklistSvMask,
1479             mGnssSvIdConfig.sbasBlacklistSvMask, mGnssSvIdConfig.navicBlacklistSvMask);
1480     // Now set required blacklisted SVs
1481     mLocApi->setBlacklistSv(mGnssSvIdConfig);
1482 }
1483 
1484 LocationError
gnssSvIdConfigUpdateSync(const std::vector<GnssSvIdSource> & blacklistedSvIds)1485 GnssAdapter::gnssSvIdConfigUpdateSync(const std::vector<GnssSvIdSource>& blacklistedSvIds)
1486 {
1487     // Clear the existing config
1488     memset(&mGnssSvIdConfig, 0, sizeof(GnssSvIdConfig));
1489 
1490     // Convert the sv id lists to masks
1491     convertToGnssSvIdConfig(blacklistedSvIds, mGnssSvIdConfig);
1492 
1493     // Now send to Modem
1494     return gnssSvIdConfigUpdateSync();
1495 }
1496 
1497 LocationError
gnssSvIdConfigUpdateSync()1498 GnssAdapter::gnssSvIdConfigUpdateSync()
1499 {
1500     LOC_LOGd("blacklist bds 0x%" PRIx64 ", glo 0x%" PRIx64
1501             ", qzss 0x%" PRIx64 ", gal 0x%" PRIx64 ", sbas 0x%" PRIx64 ", navic 0x%" PRIx64,
1502             mGnssSvIdConfig.bdsBlacklistSvMask, mGnssSvIdConfig.gloBlacklistSvMask,
1503             mGnssSvIdConfig.qzssBlacklistSvMask, mGnssSvIdConfig.galBlacklistSvMask,
1504             mGnssSvIdConfig.sbasBlacklistSvMask, mGnssSvIdConfig.navicBlacklistSvMask);
1505 
1506     // Now set required blacklisted SVs
1507     return mLocApi->setBlacklistSvSync(mGnssSvIdConfig);
1508 }
1509 
1510 void
gnssSecondaryBandConfigUpdate(LocApiResponse * locApiResponse)1511 GnssAdapter::gnssSecondaryBandConfigUpdate(LocApiResponse* locApiResponse)
1512 {
1513     LOC_LOGd("secondary band config, size %d, enabled constellation 0x%" PRIx64 ","
1514              "disabled constellation 0x%" PRIx64 "", mGnssSeconaryBandConfig.size,
1515              mGnssSeconaryBandConfig.enabledSvTypesMask,
1516              mGnssSeconaryBandConfig.blacklistedSvTypesMask);
1517     if (mGnssSeconaryBandConfig.size == sizeof(mGnssSeconaryBandConfig)) {
1518         // Now set required secondary band config
1519         mLocApi->configConstellationMultiBand(mGnssSeconaryBandConfig, locApiResponse);
1520     }
1521 }
1522 
1523 uint32_t*
gnssGetConfigCommand(GnssConfigFlagsMask configMask)1524 GnssAdapter::gnssGetConfigCommand(GnssConfigFlagsMask configMask) {
1525 
1526     // count the number of bits set
1527     GnssConfigFlagsMask flagsCopy = configMask;
1528     size_t count = 0;
1529     while (flagsCopy > 0) {
1530         if (flagsCopy & 1) {
1531             count++;
1532         }
1533         flagsCopy >>= 1;
1534     }
1535     std::string idsString = "[";
1536     uint32_t* ids = NULL;
1537     if (count > 0) {
1538         ids = new uint32_t[count];
1539         if (nullptr == ids) {
1540             LOC_LOGe("new allocation failed, fatal error.");
1541             return nullptr;
1542         }
1543         for (size_t i=0; i < count; ++i) {
1544             ids[i] = generateSessionId();
1545             IF_LOC_LOGD {
1546                 idsString += std::to_string(ids[i]) + " ";
1547             }
1548         }
1549     }
1550     idsString += "]";
1551 
1552     LOC_LOGd("ids %s flags 0x%X", idsString.c_str(), configMask);
1553 
1554     struct MsgGnssGetConfig : public LocMsg {
1555         GnssAdapter& mAdapter;
1556         LocApiBase& mApi;
1557         GnssConfigFlagsMask mConfigMask;
1558         uint32_t* mIds;
1559         size_t mCount;
1560         inline MsgGnssGetConfig(GnssAdapter& adapter,
1561                                 LocApiBase& api,
1562                                 GnssConfigFlagsMask configMask,
1563                                 uint32_t* ids,
1564                                 size_t count) :
1565             LocMsg(),
1566             mAdapter(adapter),
1567             mApi(api),
1568             mConfigMask(configMask),
1569             mCount(count),
1570             mIds(nullptr) {
1571                 if (mCount > 0) {
1572                     mIds = new uint32_t[count];
1573                     if (mIds) {
1574                         for (uint32_t index = 0; index < count; index++) {
1575                             mIds[index] = ids[index];
1576                         }
1577                     } else {
1578                         LOC_LOGe("memory allocation for mIds failed");
1579                     }
1580                 }
1581         }
1582 
1583         inline MsgGnssGetConfig(const MsgGnssGetConfig& obj) :
1584                 MsgGnssGetConfig(obj.mAdapter, obj.mApi, obj.mConfigMask,
1585                         obj.mIds, obj.mCount) {}
1586 
1587         inline virtual ~MsgGnssGetConfig()
1588         {
1589             if (nullptr != mIds) delete[] mIds;
1590         }
1591         inline virtual void proc() const {
1592             if (!mAdapter.isEngineCapabilitiesKnown()) {
1593                 mAdapter.mPendingMsgs.push_back(new MsgGnssGetConfig(*this));
1594                 return;
1595             }
1596             LocationError* errs = new LocationError[mCount];
1597             LocationError err = LOCATION_ERROR_SUCCESS;
1598             uint32_t index = 0;
1599 
1600             if (nullptr == errs) {
1601                 LOC_LOGE("%s] new allocation failed, fatal error.", __func__);
1602                 return;
1603             }
1604 
1605             if (mConfigMask & GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT) {
1606                 if (index < mCount) {
1607                     errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1608                 }
1609             }
1610             if (mConfigMask & GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT) {
1611                 if (index < mCount) {
1612                     errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1613                 }
1614             }
1615             if (mConfigMask & GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT) {
1616                 if (index < mCount) {
1617                     errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1618                 }
1619             }
1620             if (mConfigMask & GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT) {
1621                 if (index < mCount) {
1622                     errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1623                 }
1624             }
1625             if (mConfigMask & GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT) {
1626                 if (index < mCount) {
1627                     errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1628                 }
1629             }
1630             if (mConfigMask & GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT) {
1631                 if (index < mCount) {
1632                     errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1633                 }
1634             }
1635             if (mConfigMask & GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT) {
1636                 if (index < mCount) {
1637                     errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1638                 }
1639             }
1640             if (mConfigMask & GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT) {
1641                 if (index < mCount) {
1642                     errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1643                 }
1644             }
1645             if (mConfigMask & GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT) {
1646                 if (index < mCount) {
1647                     errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1648                 }
1649             }
1650             if (mConfigMask & GNSS_CONFIG_FLAGS_SUPL_MODE_BIT) {
1651                 err = LOCATION_ERROR_NOT_SUPPORTED;
1652                 if (index < mCount) {
1653                     errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1654                 }
1655             }
1656             if (mConfigMask & GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT) {
1657                 // Check if feature is supported
1658                 if (!ContextBase::isFeatureSupported(
1659                         LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02)) {
1660                     LOC_LOGe("Feature not supported.");
1661                     err = LOCATION_ERROR_NOT_SUPPORTED;
1662                 } else {
1663                     // Send request to Modem to fetch the config
1664                     mApi.getBlacklistSv();
1665                     err = LOCATION_ERROR_SUCCESS;
1666                 }
1667                 if (index < mCount) {
1668                     errs[index++] = err;
1669                 }
1670             }
1671             if (mConfigMask & GNSS_CONFIG_FLAGS_EMERGENCY_EXTENSION_SECONDS_BIT) {
1672                 err = LOCATION_ERROR_NOT_SUPPORTED;
1673                 if (index < mCount) {
1674                     errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1675                 }
1676             }
1677             if (mConfigMask & GNSS_CONFIG_FLAGS_ROBUST_LOCATION_BIT) {
1678                 uint32_t sessionId = *(mIds+index);
1679                 LocApiResponse* locApiResponse =
1680                         new LocApiResponse(*mAdapter.getContext(),
1681                                            [this, sessionId] (LocationError err) {
1682                                            mAdapter.reportResponse(err, sessionId);});
1683                 if (!locApiResponse) {
1684                     LOC_LOGe("memory alloc failed");
1685                     mAdapter.reportResponse(LOCATION_ERROR_GENERAL_FAILURE, sessionId);
1686                 } else {
1687                    mApi.getRobustLocationConfig(sessionId, locApiResponse);
1688                 }
1689             }
1690 
1691             if (mConfigMask & GNSS_CONFIG_FLAGS_MIN_GPS_WEEK_BIT) {
1692                 uint32_t sessionId = *(mIds+index);
1693                 LocApiResponse* locApiResponse =
1694                         new LocApiResponse(*mAdapter.getContext(),
1695                                            [this, sessionId] (LocationError err) {
1696                                            mAdapter.reportResponse(err, sessionId);});
1697                 if (!locApiResponse) {
1698                     LOC_LOGe("memory alloc failed");
1699                     mAdapter.reportResponse(LOCATION_ERROR_GENERAL_FAILURE, sessionId);
1700                 } else {
1701                    mApi.getMinGpsWeek(sessionId, locApiResponse);
1702                 }
1703             }
1704 
1705             if (mConfigMask & GNSS_CONFIG_FLAGS_MIN_SV_ELEVATION_BIT) {
1706                 uint32_t sessionId = *(mIds+index);
1707                 LocApiResponse* locApiResponse =
1708                         new LocApiResponse(*mAdapter.getContext(),
1709                                            [this, sessionId] (LocationError err) {
1710                                            mAdapter.reportResponse(err, sessionId);});
1711                 if (!locApiResponse) {
1712                     LOC_LOGe("memory alloc failed");
1713                     mAdapter.reportResponse(LOCATION_ERROR_GENERAL_FAILURE, sessionId);
1714                 } else {
1715                     mApi.getParameter(sessionId, GNSS_CONFIG_FLAGS_MIN_SV_ELEVATION_BIT,
1716                                       locApiResponse);
1717                 }
1718             }
1719 
1720             mAdapter.reportResponse(index, errs, mIds);
1721             delete[] errs;
1722 
1723         }
1724     };
1725 
1726     if (NULL != ids) {
1727         sendMsg(new MsgGnssGetConfig(*this, *mLocApi, configMask, ids, count));
1728     } else {
1729         LOC_LOGe("No GNSS config items to Get");
1730     }
1731 
1732     return ids;
1733 }
1734 
1735 bool
convertToGnssSvIdConfig(const std::vector<GnssSvIdSource> & blacklistedSvIds,GnssSvIdConfig & config)1736 GnssAdapter::convertToGnssSvIdConfig(
1737         const std::vector<GnssSvIdSource>& blacklistedSvIds, GnssSvIdConfig& config)
1738 {
1739     bool retVal = false;
1740     config.size = sizeof(GnssSvIdConfig);
1741 
1742     // Empty vector => Clear any previous blacklisted SVs
1743     if (0 == blacklistedSvIds.size()) {
1744         config.gloBlacklistSvMask = 0;
1745         config.bdsBlacklistSvMask = 0;
1746         config.qzssBlacklistSvMask = 0;
1747         config.galBlacklistSvMask = 0;
1748         config.sbasBlacklistSvMask = 0;
1749         config.navicBlacklistSvMask = 0;
1750         retVal = true;
1751     } else {
1752         // Parse the vector and convert SV IDs to mask values
1753         for (GnssSvIdSource source : blacklistedSvIds) {
1754             uint64_t* svMaskPtr = NULL;
1755             GnssSvId initialSvId = 0;
1756             uint16_t svIndexOffset = 0;
1757             switch(source.constellation) {
1758             case GNSS_SV_TYPE_GLONASS:
1759                 svMaskPtr = &config.gloBlacklistSvMask;
1760                 initialSvId = GNSS_SV_CONFIG_GLO_INITIAL_SV_ID;
1761                 break;
1762             case GNSS_SV_TYPE_BEIDOU:
1763                 svMaskPtr = &config.bdsBlacklistSvMask;
1764                 initialSvId = GNSS_SV_CONFIG_BDS_INITIAL_SV_ID;
1765                 break;
1766             case GNSS_SV_TYPE_QZSS:
1767                 svMaskPtr = &config.qzssBlacklistSvMask;
1768                 initialSvId = GNSS_SV_CONFIG_QZSS_INITIAL_SV_ID;
1769                 break;
1770             case GNSS_SV_TYPE_GALILEO:
1771                 svMaskPtr = &config.galBlacklistSvMask;
1772                 initialSvId = GNSS_SV_CONFIG_GAL_INITIAL_SV_ID;
1773                 break;
1774             case GNSS_SV_TYPE_SBAS:
1775                 // SBAS does not support enable/disable whole constellation
1776                 // so do not set up svTypeMask for SBAS
1777                 svMaskPtr = &config.sbasBlacklistSvMask;
1778                 // SBAS currently has two ranges, [120, 158] and [183, 191]
1779                 if (0 == source.svId) {
1780                     LOC_LOGd("blacklist all SBAS SV");
1781                 } else if (source.svId >= GNSS_SV_CONFIG_SBAS_INITIAL2_SV_ID) {
1782                     // handle SV id in range [183, 191]
1783                     initialSvId = GNSS_SV_CONFIG_SBAS_INITIAL2_SV_ID;
1784                     svIndexOffset = GNSS_SV_CONFIG_SBAS_INITIAL_SV_LENGTH;
1785                 } else if ((source.svId >= GNSS_SV_CONFIG_SBAS_INITIAL_SV_ID) &&
1786                            (source.svId < (GNSS_SV_CONFIG_SBAS_INITIAL_SV_ID +
1787                                            GNSS_SV_CONFIG_SBAS_INITIAL_SV_LENGTH))){
1788                         // handle SV id in range of [120, 158]
1789                         initialSvId = GNSS_SV_CONFIG_SBAS_INITIAL_SV_ID;
1790                     } else {
1791                         LOC_LOGe("invalid SBAS sv id %d", source.svId);
1792                         svMaskPtr = nullptr;
1793                     }
1794                     break;
1795             case GNSS_SV_TYPE_NAVIC:
1796                  svMaskPtr = &config.navicBlacklistSvMask;
1797                  initialSvId = GNSS_SV_CONFIG_NAVIC_INITIAL_SV_ID;
1798                 break;
1799             default:
1800                 break;
1801             }
1802 
1803             if (NULL == svMaskPtr) {
1804                 LOC_LOGe("Invalid constellation %d", source.constellation);
1805             } else {
1806                 // SV ID 0 = All SV IDs
1807                 if (0 == source.svId) {
1808                     *svMaskPtr = GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK;
1809                 } else if (source.svId < initialSvId || source.svId >= initialSvId + 64) {
1810                     LOC_LOGe("Invalid sv id %d for sv type %d",
1811                             source.svId, source.constellation);
1812                 } else {
1813                     uint32_t shiftCnt = source.svId + svIndexOffset - initialSvId;
1814                     *svMaskPtr |= (1ULL << shiftCnt);
1815                 }
1816             }
1817         }
1818 
1819         // Return true if any one source is valid
1820         if (0 != config.gloBlacklistSvMask ||
1821                 0 != config.bdsBlacklistSvMask ||
1822                 0 != config.galBlacklistSvMask ||
1823                 0 != config.qzssBlacklistSvMask ||
1824                 0 != config.sbasBlacklistSvMask ||
1825                 0 != config.navicBlacklistSvMask) {
1826             retVal = true;
1827         }
1828     }
1829 
1830     LOC_LOGd("blacklist bds 0x%" PRIx64 ", glo 0x%" PRIx64
1831             ", qzss 0x%" PRIx64 ", gal 0x%" PRIx64 ", sbas 0x%" PRIx64 ", navic 0x%" PRIx64,
1832              config.bdsBlacklistSvMask, config.gloBlacklistSvMask,
1833              config.qzssBlacklistSvMask, config.galBlacklistSvMask,
1834             config.sbasBlacklistSvMask, config.navicBlacklistSvMask);
1835 
1836     return retVal;
1837 }
1838 
convertFromGnssSvIdConfig(const GnssSvIdConfig & svConfig,std::vector<GnssSvIdSource> & blacklistedSvIds)1839 void GnssAdapter::convertFromGnssSvIdConfig(
1840         const GnssSvIdConfig& svConfig, std::vector<GnssSvIdSource>& blacklistedSvIds)
1841 {
1842     // Convert blacklisted SV mask values to vectors
1843     if (svConfig.bdsBlacklistSvMask) {
1844         convertGnssSvIdMaskToList(
1845                 svConfig.bdsBlacklistSvMask, blacklistedSvIds,
1846                 GNSS_SV_CONFIG_BDS_INITIAL_SV_ID, GNSS_SV_TYPE_BEIDOU);
1847     }
1848     if (svConfig.galBlacklistSvMask) {
1849         convertGnssSvIdMaskToList(
1850                 svConfig.galBlacklistSvMask, blacklistedSvIds,
1851                 GNSS_SV_CONFIG_GAL_INITIAL_SV_ID, GNSS_SV_TYPE_GALILEO);
1852     }
1853     if (svConfig.gloBlacklistSvMask) {
1854         convertGnssSvIdMaskToList(
1855                 svConfig.gloBlacklistSvMask, blacklistedSvIds,
1856                 GNSS_SV_CONFIG_GLO_INITIAL_SV_ID, GNSS_SV_TYPE_GLONASS);
1857     }
1858     if (svConfig.qzssBlacklistSvMask) {
1859         convertGnssSvIdMaskToList(
1860                 svConfig.qzssBlacklistSvMask, blacklistedSvIds,
1861                 GNSS_SV_CONFIG_QZSS_INITIAL_SV_ID, GNSS_SV_TYPE_QZSS);
1862     }
1863     if (svConfig.sbasBlacklistSvMask) {
1864         // SBAS - SV 120 to 158, maps to 0 to 38
1865         //        SV 183 to 191, maps to 39 to 47
1866         uint64_t sbasBlacklistSvMask = svConfig.sbasBlacklistSvMask;
1867         // operate on 120 and 158 first
1868         sbasBlacklistSvMask <<= (64 - GNSS_SV_CONFIG_SBAS_INITIAL_SV_LENGTH);
1869         sbasBlacklistSvMask >>= (64 - GNSS_SV_CONFIG_SBAS_INITIAL_SV_LENGTH);
1870         convertGnssSvIdMaskToList(
1871                 sbasBlacklistSvMask, blacklistedSvIds,
1872                 GNSS_SV_CONFIG_SBAS_INITIAL_SV_ID, GNSS_SV_TYPE_SBAS);
1873         // operate on the second range
1874         sbasBlacklistSvMask = svConfig.sbasBlacklistSvMask;
1875         sbasBlacklistSvMask >>= GNSS_SV_CONFIG_SBAS_INITIAL_SV_LENGTH;
1876         convertGnssSvIdMaskToList(
1877                 sbasBlacklistSvMask, blacklistedSvIds,
1878                 GNSS_SV_CONFIG_SBAS_INITIAL2_SV_ID, GNSS_SV_TYPE_SBAS);
1879     }
1880     if (svConfig.navicBlacklistSvMask) {
1881         convertGnssSvIdMaskToList(
1882                 svConfig.navicBlacklistSvMask, blacklistedSvIds,
1883                 GNSS_SV_CONFIG_NAVIC_INITIAL_SV_ID, GNSS_SV_TYPE_NAVIC);
1884     }
1885 }
1886 
convertGnssSvIdMaskToList(uint64_t svIdMask,std::vector<GnssSvIdSource> & svIds,GnssSvId initialSvId,GnssSvType svType)1887 void GnssAdapter::convertGnssSvIdMaskToList(
1888         uint64_t svIdMask, std::vector<GnssSvIdSource>& svIds,
1889         GnssSvId initialSvId, GnssSvType svType)
1890 {
1891     GnssSvIdSource source = {};
1892     source.size = sizeof(GnssSvIdSource);
1893     source.constellation = svType;
1894 
1895     // SV ID 0 => All SV IDs in mask
1896     if (GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK == svIdMask) {
1897         LOC_LOGd("blacklist all SVs in constellation %d", source.constellation);
1898         source.svId = 0;
1899         svIds.push_back(source);
1900         return;
1901     }
1902 
1903     // Convert each bit in svIdMask to vector entry
1904     uint32_t bitNumber = 0;
1905     while (svIdMask > 0) {
1906         if (svIdMask & 0x1) {
1907             source.svId = bitNumber + initialSvId;
1908             // SBAS has two ranges:
1909             // SBAS - SV 120 to 158, maps to 0 to 38
1910             //        SV 183 to 191, maps to 39 to 47
1911             // #define GNSS_SV_CONFIG_SBAS_INITIAL_SV_ID     120
1912             // #define GNSS_SV_CONFIG_SBAS_INITIAL_SV_LENGTH 39
1913             // #define GNSS_SV_CONFIG_SBAS_INITIAL2_SV_ID    183
1914             if (svType == GNSS_SV_TYPE_SBAS) {
1915                 if (bitNumber >= GNSS_SV_CONFIG_SBAS_INITIAL_SV_LENGTH) {
1916                     source.svId = bitNumber - GNSS_SV_CONFIG_SBAS_INITIAL_SV_LENGTH +
1917                                   GNSS_SV_CONFIG_SBAS_INITIAL2_SV_ID;
1918                 }
1919             }
1920             svIds.push_back(source);
1921         }
1922         bitNumber++;
1923         svIdMask >>= 1;
1924     }
1925 }
1926 
reportGnssSvIdConfigEvent(const GnssSvIdConfig & config)1927 void GnssAdapter::reportGnssSvIdConfigEvent(const GnssSvIdConfig& config)
1928 {
1929     struct MsgReportGnssSvIdConfig : public LocMsg {
1930         GnssAdapter& mAdapter;
1931         const GnssSvIdConfig mConfig;
1932         inline MsgReportGnssSvIdConfig(GnssAdapter& adapter,
1933                                  const GnssSvIdConfig& config) :
1934             LocMsg(),
1935             mAdapter(adapter),
1936             mConfig(config) {}
1937         inline virtual void proc() const {
1938             mAdapter.reportGnssSvIdConfig(mConfig);
1939         }
1940     };
1941 
1942     sendMsg(new MsgReportGnssSvIdConfig(*this, config));
1943 }
1944 
reportGnssSvIdConfig(const GnssSvIdConfig & svIdConfig)1945 void GnssAdapter::reportGnssSvIdConfig(const GnssSvIdConfig& svIdConfig)
1946 {
1947     GnssConfig config = {};
1948     config.size = sizeof(GnssConfig);
1949 
1950     // Invoke control clients config callback
1951     if (nullptr != mControlCallbacks.gnssConfigCb &&
1952             svIdConfig.size == sizeof(GnssSvIdConfig)) {
1953 
1954         convertFromGnssSvIdConfig(svIdConfig, config.blacklistedSvIds);
1955         if (config.blacklistedSvIds.size() > 0) {
1956             config.flags |= GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT;
1957         }
1958         LOC_LOGd("blacklist bds 0x%" PRIx64 ", glo 0x%" PRIx64 ", "
1959                  "qzss 0x%" PRIx64 ", gal 0x%" PRIx64 ", sbas 0x%" PRIx64 ", navic 0x%" PRIx64,
1960                  svIdConfig.bdsBlacklistSvMask, svIdConfig.gloBlacklistSvMask,
1961                  svIdConfig.qzssBlacklistSvMask, svIdConfig.galBlacklistSvMask,
1962                  svIdConfig.sbasBlacklistSvMask,  svIdConfig.navicBlacklistSvMask);
1963         // use 0 session id to indicate that receiver does not yet care about session id
1964         mControlCallbacks.gnssConfigCb(0, config);
1965     } else {
1966         LOC_LOGe("Failed to report, size %d", (uint32_t)config.size);
1967     }
1968 }
1969 
1970 void
gnssUpdateSvTypeConfigCommand(GnssSvTypeConfig config)1971 GnssAdapter::gnssUpdateSvTypeConfigCommand(GnssSvTypeConfig config)
1972 {
1973     struct MsgGnssUpdateSvTypeConfig : public LocMsg {
1974         GnssAdapter* mAdapter;
1975         LocApiBase* mApi;
1976         GnssSvTypeConfig mConfig;
1977         inline MsgGnssUpdateSvTypeConfig(
1978                 GnssAdapter* adapter,
1979                 LocApiBase* api,
1980                 GnssSvTypeConfig& config) :
1981             LocMsg(),
1982             mAdapter(adapter),
1983             mApi(api),
1984             mConfig(config) {}
1985         inline virtual void proc() const {
1986             if (!mAdapter->isEngineCapabilitiesKnown()) {
1987                 mAdapter->mPendingMsgs.push_back(new MsgGnssUpdateSvTypeConfig(*this));
1988                 return;
1989             }
1990             // Check if feature is supported
1991             if (!ContextBase::isFeatureSupported(
1992                     LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02)) {
1993                 LOC_LOGe("Feature not supported.");
1994             } else {
1995                 // Send update request to modem
1996                 mAdapter->gnssSvTypeConfigUpdate(mConfig);
1997             }
1998         }
1999     };
2000 
2001     sendMsg(new MsgGnssUpdateSvTypeConfig(this, mLocApi, config));
2002 }
2003 
2004 void
gnssSvTypeConfigUpdate(const GnssSvTypeConfig & config)2005 GnssAdapter::gnssSvTypeConfigUpdate(const GnssSvTypeConfig& config)
2006 {
2007     // Gather bits removed from enabled mask
2008     GnssSvTypesMask enabledRemoved = mGnssSvTypeConfig.enabledSvTypesMask &
2009             (mGnssSvTypeConfig.enabledSvTypesMask ^ config.enabledSvTypesMask);
2010     // Send reset if any constellation is removed from the enabled list
2011     bool sendReset = (enabledRemoved != 0);
2012     // Save new config and update
2013     gnssSetSvTypeConfig(config);
2014     gnssSvTypeConfigUpdate(sendReset);
2015 }
2016 
2017 void
gnssSvTypeConfigUpdate(bool sendReset)2018 GnssAdapter::gnssSvTypeConfigUpdate(bool sendReset)
2019 {
2020     LOC_LOGd("size %" PRIu32" constellations blacklisted 0x%" PRIx64 ", enabled 0x%" PRIx64
2021              ", sendReset %d",
2022              mGnssSvTypeConfig.size, mGnssSvTypeConfig.blacklistedSvTypesMask,
2023              mGnssSvTypeConfig.enabledSvTypesMask, sendReset);
2024 
2025     LOC_LOGd("blacklist bds 0x%" PRIx64 ", glo 0x%" PRIx64
2026             ", qzss 0x%" PRIx64 ", gal 0x%" PRIx64 ", sbas 0x%" PRIx64 ", Navic 0x%" PRIx64,
2027             mGnssSvIdConfig.bdsBlacklistSvMask, mGnssSvIdConfig.gloBlacklistSvMask,
2028             mGnssSvIdConfig.qzssBlacklistSvMask, mGnssSvIdConfig.galBlacklistSvMask,
2029             mGnssSvIdConfig.sbasBlacklistSvMask, mGnssSvIdConfig.navicBlacklistSvMask);
2030 
2031     LOC_LOGd("blacklist bds 0x%" PRIx64 ", glo 0x%" PRIx64
2032             ", qzss 0x%" PRIx64 ", gal 0x%" PRIx64 ", sbas 0x%" PRIx64 ", Navic 0x%" PRIx64,
2033             mGnssSvIdConfig.bdsBlacklistSvMask, mGnssSvIdConfig.gloBlacklistSvMask,
2034             mGnssSvIdConfig.qzssBlacklistSvMask, mGnssSvIdConfig.galBlacklistSvMask,
2035             mGnssSvIdConfig.sbasBlacklistSvMask, mGnssSvIdConfig.navicBlacklistSvMask);
2036 
2037     if (mGnssSvTypeConfig.size == sizeof(mGnssSvTypeConfig)) {
2038 
2039         if (sendReset) {
2040             mLocApi->resetConstellationControl();
2041         }
2042 
2043         GnssSvIdConfig blacklistConfig = {};
2044         // Revert to previously blacklisted SVs for each enabled constellation
2045         blacklistConfig = mGnssSvIdConfig;
2046         // Blacklist all SVs for each disabled constellation
2047         if (mGnssSvTypeConfig.blacklistedSvTypesMask) {
2048             if (mGnssSvTypeConfig.blacklistedSvTypesMask & GNSS_SV_TYPES_MASK_GLO_BIT) {
2049                 blacklistConfig.gloBlacklistSvMask = GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK;
2050             }
2051             if (mGnssSvTypeConfig.blacklistedSvTypesMask & GNSS_SV_TYPES_MASK_BDS_BIT) {
2052                 blacklistConfig.bdsBlacklistSvMask = GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK;
2053             }
2054             if (mGnssSvTypeConfig.blacklistedSvTypesMask & GNSS_SV_TYPES_MASK_QZSS_BIT) {
2055                 blacklistConfig.qzssBlacklistSvMask = GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK;
2056             }
2057             if (mGnssSvTypeConfig.blacklistedSvTypesMask & GNSS_SV_TYPES_MASK_GAL_BIT) {
2058                 blacklistConfig.galBlacklistSvMask = GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK;
2059             }
2060             if (mGnssSvTypeConfig.blacklistedSvTypesMask & GNSS_SV_TYPES_MASK_NAVIC_BIT) {
2061                 blacklistConfig.navicBlacklistSvMask = GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK;
2062             }
2063         }
2064 
2065         // Send blacklist info
2066         mLocApi->setBlacklistSv(blacklistConfig);
2067 
2068         // Send only enabled constellation config
2069         if (mGnssSvTypeConfig.enabledSvTypesMask) {
2070             GnssSvTypeConfig svTypeConfig = {sizeof(GnssSvTypeConfig), 0, 0};
2071             svTypeConfig.enabledSvTypesMask = mGnssSvTypeConfig.enabledSvTypesMask;
2072             mLocApi->setConstellationControl(svTypeConfig);
2073         }
2074     }
2075 }
2076 
2077 void
gnssGetSvTypeConfigCommand(GnssSvTypeConfigCallback callback)2078 GnssAdapter::gnssGetSvTypeConfigCommand(GnssSvTypeConfigCallback callback)
2079 {
2080     struct MsgGnssGetSvTypeConfig : public LocMsg {
2081         GnssAdapter* mAdapter;
2082         LocApiBase* mApi;
2083         GnssSvTypeConfigCallback mCallback;
2084         inline MsgGnssGetSvTypeConfig(
2085                 GnssAdapter* adapter,
2086                 LocApiBase* api,
2087                 GnssSvTypeConfigCallback callback) :
2088             LocMsg(),
2089             mAdapter(adapter),
2090             mApi(api),
2091             mCallback(callback) {}
2092         inline virtual void proc() const {
2093             if (!mAdapter->isEngineCapabilitiesKnown()) {
2094                 mAdapter->mPendingMsgs.push_back(new MsgGnssGetSvTypeConfig(*this));
2095                 return;
2096             }
2097             if (!ContextBase::isFeatureSupported(
2098                     LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02)) {
2099                 LOC_LOGe("Feature not supported.");
2100             } else {
2101                 // Save the callback
2102                 mAdapter->gnssSetSvTypeConfigCallback(mCallback);
2103                 // Send GET request to modem
2104                 mApi->getConstellationControl();
2105             }
2106         }
2107     };
2108 
2109     sendMsg(new MsgGnssGetSvTypeConfig(this, mLocApi, callback));
2110 }
2111 
2112 void
gnssResetSvTypeConfigCommand()2113 GnssAdapter::gnssResetSvTypeConfigCommand()
2114 {
2115     struct MsgGnssResetSvTypeConfig : public LocMsg {
2116         GnssAdapter* mAdapter;
2117         LocApiBase* mApi;
2118         inline MsgGnssResetSvTypeConfig(
2119                 GnssAdapter* adapter,
2120                 LocApiBase* api) :
2121             LocMsg(),
2122             mAdapter(adapter),
2123             mApi(api) {}
2124         inline virtual void proc() const {
2125             if (!mAdapter->isEngineCapabilitiesKnown()) {
2126                 mAdapter->mPendingMsgs.push_back(new MsgGnssResetSvTypeConfig(*this));
2127                 return;
2128             }
2129             if (!ContextBase::isFeatureSupported(
2130                     LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02)) {
2131                 LOC_LOGe("Feature not supported.");
2132             } else {
2133                 // Reset constellation config
2134                 mAdapter->gnssSetSvTypeConfig({sizeof(GnssSvTypeConfig), 0, 0});
2135                 // Re-enforce SV blacklist config
2136                 mAdapter->gnssSvIdConfigUpdate();
2137                 // Send reset request to modem
2138                 mApi->resetConstellationControl();
2139             }
2140         }
2141     };
2142 
2143     sendMsg(new MsgGnssResetSvTypeConfig(this, mLocApi));
2144 }
2145 
reportGnssSvTypeConfigEvent(const GnssSvTypeConfig & config)2146 void GnssAdapter::reportGnssSvTypeConfigEvent(const GnssSvTypeConfig& config)
2147 {
2148     struct MsgReportGnssSvTypeConfig : public LocMsg {
2149         GnssAdapter& mAdapter;
2150         const GnssSvTypeConfig mConfig;
2151         inline MsgReportGnssSvTypeConfig(GnssAdapter& adapter,
2152                                  const GnssSvTypeConfig& config) :
2153             LocMsg(),
2154             mAdapter(adapter),
2155             mConfig(config) {}
2156         inline virtual void proc() const {
2157             mAdapter.reportGnssSvTypeConfig(mConfig);
2158         }
2159     };
2160 
2161     sendMsg(new MsgReportGnssSvTypeConfig(*this, config));
2162 }
2163 
reportGnssSvTypeConfig(const GnssSvTypeConfig & config)2164 void GnssAdapter::reportGnssSvTypeConfig(const GnssSvTypeConfig& config)
2165 {
2166     // Invoke Get SV Type Callback
2167     if (NULL != mGnssSvTypeConfigCb &&
2168             config.size == sizeof(GnssSvTypeConfig)) {
2169         LOC_LOGd("constellations blacklisted 0x%" PRIx64 ", enabled 0x%" PRIx64,
2170                  config.blacklistedSvTypesMask, config.enabledSvTypesMask);
2171         mGnssSvTypeConfigCb(config);
2172     } else {
2173         LOC_LOGe("Failed to report, size %d", (uint32_t)config.size);
2174     }
2175 }
2176 
deleteAidingData(const GnssAidingData & data,uint32_t sessionId)2177 void GnssAdapter::deleteAidingData(const GnssAidingData &data, uint32_t sessionId) {
2178     struct timespec bootDeleteAidingDataTime;
2179     int64_t bootDeleteTimeMs;
2180     if (clock_gettime(CLOCK_BOOTTIME, &bootDeleteAidingDataTime) == 0) {
2181         bootDeleteTimeMs = bootDeleteAidingDataTime.tv_sec * 1000000;
2182         int64_t diffTimeBFirSecDelete = bootDeleteTimeMs - mLastDeleteAidingDataTime;
2183         if (diffTimeBFirSecDelete > DELETE_AIDING_DATA_EXPECTED_TIME_MS) {
2184             mLocApi->deleteAidingData(data, new LocApiResponse(*getContext(),
2185                     [this, sessionId] (LocationError err) {
2186                         reportResponse(err, sessionId);
2187                     }));
2188             mLastDeleteAidingDataTime = bootDeleteTimeMs;
2189        }
2190    }
2191 }
2192 
2193 uint32_t
gnssDeleteAidingDataCommand(GnssAidingData & data)2194 GnssAdapter::gnssDeleteAidingDataCommand(GnssAidingData& data)
2195 {
2196     uint32_t sessionId = generateSessionId();
2197     LOC_LOGD("%s]: id %u", __func__, sessionId);
2198 
2199     struct MsgDeleteAidingData : public LocMsg {
2200         GnssAdapter& mAdapter;
2201         uint32_t mSessionId;
2202         GnssAidingData mData;
2203         inline MsgDeleteAidingData(GnssAdapter& adapter,
2204                                    uint32_t sessionId,
2205                                    GnssAidingData& data) :
2206             LocMsg(),
2207             mAdapter(adapter),
2208             mSessionId(sessionId),
2209             mData(data) {}
2210         inline virtual void proc() const {
2211             if ((mData.posEngineMask & STANDARD_POSITIONING_ENGINE) != 0) {
2212                 mAdapter.deleteAidingData(mData, mSessionId);
2213                 SystemStatus* s = mAdapter.getSystemStatus();
2214                 if ((nullptr != s) && (mData.deleteAll)) {
2215                     s->setDefaultGnssEngineStates();
2216                 }
2217             }
2218 
2219             bool retVal = mAdapter.mEngHubProxy->gnssDeleteAidingData(mData);
2220             // When SPE engine is invoked, responseCb will be invoked
2221             // from QMI Loc API call.
2222             // When SPE engine is not invoked, we also need to deliver responseCb
2223             if ((mData.posEngineMask & STANDARD_POSITIONING_ENGINE) == 0) {
2224                 LocationError err = LOCATION_ERROR_NOT_SUPPORTED;
2225                 if (retVal == true) {
2226                     err = LOCATION_ERROR_SUCCESS;
2227                 }
2228                 mAdapter.reportResponse(err, mSessionId);
2229             }
2230         }
2231     };
2232 
2233     sendMsg(new MsgDeleteAidingData(*this, sessionId, data));
2234     return sessionId;
2235 }
2236 
2237 void
gnssUpdateXtraThrottleCommand(const bool enabled)2238 GnssAdapter::gnssUpdateXtraThrottleCommand(const bool enabled)
2239 {
2240     LOC_LOGD("%s] enabled:%d", __func__, enabled);
2241 
2242     struct UpdateXtraThrottleMsg : public LocMsg {
2243         GnssAdapter& mAdapter;
2244         const bool mEnabled;
2245         inline UpdateXtraThrottleMsg(GnssAdapter& adapter, const bool enabled) :
2246             LocMsg(),
2247             mAdapter(adapter),
2248             mEnabled(enabled) {}
2249         inline virtual void proc() const {
2250                 mAdapter.mXtraObserver.updateXtraThrottle(mEnabled);
2251         }
2252     };
2253 
2254     sendMsg(new UpdateXtraThrottleMsg(*this, enabled));
2255 }
2256 
2257 void
injectLocationCommand(double latitude,double longitude,float accuracy)2258 GnssAdapter::injectLocationCommand(double latitude, double longitude, float accuracy)
2259 {
2260     LOC_LOGD("%s]: latitude %8.4f longitude %8.4f accuracy %8.4f",
2261              __func__, latitude, longitude, accuracy);
2262 
2263     struct MsgInjectLocation : public LocMsg {
2264         LocApiBase& mApi;
2265         ContextBase& mContext;
2266         BlockCPIInfo& mBlockCPI;
2267         double mLatitude;
2268         double mLongitude;
2269         float mAccuracy;
2270         bool mOnDemandCpi;
2271         inline MsgInjectLocation(LocApiBase& api,
2272                                  ContextBase& context,
2273                                  BlockCPIInfo& blockCPIInfo,
2274                                  double latitude,
2275                                  double longitude,
2276                                  float accuracy,
2277                                  bool onDemandCpi) :
2278             LocMsg(),
2279             mApi(api),
2280             mContext(context),
2281             mBlockCPI(blockCPIInfo),
2282             mLatitude(latitude),
2283             mLongitude(longitude),
2284             mAccuracy(accuracy),
2285             mOnDemandCpi(onDemandCpi) {}
2286         inline virtual void proc() const {
2287             if ((uptimeMillis() <= mBlockCPI.blockedTillTsMs) &&
2288                 (fabs(mLatitude-mBlockCPI.latitude) <= mBlockCPI.latLonDiffThreshold) &&
2289                 (fabs(mLongitude-mBlockCPI.longitude) <= mBlockCPI.latLonDiffThreshold)) {
2290 
2291                 LOC_LOGD("%s]: positon injection blocked: lat: %f, lon: %f, accuracy: %f",
2292                          __func__, mLatitude, mLongitude, mAccuracy);
2293 
2294             } else {
2295                 mApi.injectPosition(mLatitude, mLongitude, mAccuracy, mOnDemandCpi);
2296             }
2297         }
2298     };
2299 
2300     sendMsg(new MsgInjectLocation(*mLocApi, *mContext, mBlockCPIInfo,
2301                                   latitude, longitude, accuracy, mOdcpiRequestActive));
2302 }
2303 
2304 void
injectLocationExtCommand(const GnssLocationInfoNotification & locationInfo)2305 GnssAdapter::injectLocationExtCommand(const GnssLocationInfoNotification &locationInfo)
2306 {
2307     LOC_LOGd("latitude %8.4f longitude %8.4f accuracy %8.4f, tech mask 0x%x",
2308              locationInfo.location.latitude, locationInfo.location.longitude,
2309              locationInfo.location.accuracy, locationInfo.location.techMask);
2310 
2311     struct MsgInjectLocationExt : public LocMsg {
2312         LocApiBase& mApi;
2313         ContextBase& mContext;
2314         GnssLocationInfoNotification mLocationInfo;
2315         inline MsgInjectLocationExt(LocApiBase& api,
2316                                     ContextBase& context,
2317                                     GnssLocationInfoNotification locationInfo) :
2318             LocMsg(),
2319             mApi(api),
2320             mContext(context),
2321             mLocationInfo(locationInfo) {}
2322         inline virtual void proc() const {
2323             // false to indicate for none-ODCPI
2324             mApi.injectPosition(mLocationInfo, false);
2325         }
2326     };
2327 
2328     sendMsg(new MsgInjectLocationExt(*mLocApi, *mContext, locationInfo));
2329 }
2330 
2331 void
injectTimeCommand(int64_t time,int64_t timeReference,int32_t uncertainty)2332 GnssAdapter::injectTimeCommand(int64_t time, int64_t timeReference, int32_t uncertainty)
2333 {
2334     LOC_LOGD("%s]: time %lld timeReference %lld uncertainty %d",
2335              __func__, (long long)time, (long long)timeReference, uncertainty);
2336 
2337     struct MsgInjectTime : public LocMsg {
2338         LocApiBase& mApi;
2339         ContextBase& mContext;
2340         int64_t mTime;
2341         int64_t mTimeReference;
2342         int32_t mUncertainty;
2343         inline MsgInjectTime(LocApiBase& api,
2344                              ContextBase& context,
2345                              int64_t time,
2346                              int64_t timeReference,
2347                              int32_t uncertainty) :
2348             LocMsg(),
2349             mApi(api),
2350             mContext(context),
2351             mTime(time),
2352             mTimeReference(timeReference),
2353             mUncertainty(uncertainty) {}
2354         inline virtual void proc() const {
2355             mApi.setTime(mTime, mTimeReference, mUncertainty);
2356         }
2357     };
2358 
2359     sendMsg(new MsgInjectTime(*mLocApi, *mContext, time, timeReference, uncertainty));
2360 }
2361 
2362 // This command is to called to block the position to be injected to the modem.
2363 // This can happen for network position that comes from modem.
2364 void
blockCPICommand(double latitude,double longitude,float accuracy,int blockDurationMsec,double latLonDiffThreshold)2365 GnssAdapter::blockCPICommand(double latitude, double longitude,
2366                              float accuracy, int blockDurationMsec,
2367                              double latLonDiffThreshold)
2368 {
2369     struct MsgBlockCPI : public LocMsg {
2370         BlockCPIInfo& mDstCPIInfo;
2371         BlockCPIInfo mSrcCPIInfo;
2372 
2373         inline MsgBlockCPI(BlockCPIInfo& dstCPIInfo,
2374                            BlockCPIInfo& srcCPIInfo) :
2375             mDstCPIInfo(dstCPIInfo),
2376             mSrcCPIInfo(srcCPIInfo) {}
2377         inline virtual void proc() const {
2378             // in the same hal thread, save the cpi to be blocked
2379             // the global variable
2380             mDstCPIInfo = mSrcCPIInfo;
2381         }
2382     };
2383 
2384     // construct the new block CPI info and queue on the same thread
2385     // for processing
2386     BlockCPIInfo blockCPIInfo;
2387     blockCPIInfo.latitude = latitude;
2388     blockCPIInfo.longitude = longitude;
2389     blockCPIInfo.accuracy = accuracy;
2390     blockCPIInfo.blockedTillTsMs = uptimeMillis() + blockDurationMsec;
2391     blockCPIInfo.latLonDiffThreshold = latLonDiffThreshold;
2392 
2393     LOC_LOGD("%s]: block CPI lat: %f, lon: %f ", __func__, latitude, longitude);
2394     // send a message to record down the coarse position
2395     // to be blocked from injection in the master copy (mBlockCPIInfo)
2396     sendMsg(new MsgBlockCPI(mBlockCPIInfo, blockCPIInfo));
2397 }
2398 
2399 void
updateSystemPowerState(PowerStateType systemPowerState)2400 GnssAdapter::updateSystemPowerState(PowerStateType systemPowerState) {
2401     if (POWER_STATE_UNKNOWN != systemPowerState) {
2402         mSystemPowerState = systemPowerState;
2403         mLocApi->updateSystemPowerState(mSystemPowerState);
2404     }
2405 }
2406 
2407 void
updateSystemPowerStateCommand(PowerStateType systemPowerState)2408 GnssAdapter::updateSystemPowerStateCommand(PowerStateType systemPowerState) {
2409     LOC_LOGd("power event %d", systemPowerState);
2410 
2411     struct MsgUpdatePowerState : public LocMsg {
2412         GnssAdapter& mAdapter;
2413         PowerStateType mSystemPowerState;
2414 
2415         inline MsgUpdatePowerState(GnssAdapter& adapter,
2416                                    PowerStateType systemPowerState) :
2417             LocMsg(),
2418             mAdapter(adapter),
2419             mSystemPowerState(systemPowerState) {}
2420         inline virtual void proc() const {
2421             mAdapter.updateSystemPowerState(mSystemPowerState);
2422         }
2423     };
2424 
2425     sendMsg(new MsgUpdatePowerState(*this, systemPowerState));
2426 }
2427 
2428 void
addClientCommand(LocationAPI * client,const LocationCallbacks & callbacks)2429 GnssAdapter::addClientCommand(LocationAPI* client, const LocationCallbacks& callbacks)
2430 {
2431     LOC_LOGD("%s]: client %p", __func__, client);
2432 
2433     struct MsgAddClient : public LocMsg {
2434         GnssAdapter& mAdapter;
2435         LocationAPI* mClient;
2436         const LocationCallbacks mCallbacks;
2437         inline MsgAddClient(GnssAdapter& adapter,
2438                             LocationAPI* client,
2439                             const LocationCallbacks& callbacks) :
2440             LocMsg(),
2441             mAdapter(adapter),
2442             mClient(client),
2443             mCallbacks(callbacks) {}
2444         inline virtual void proc() const {
2445             // check whether we need to notify client of cached location system info
2446             mAdapter.notifyClientOfCachedLocationSystemInfo(mClient, mCallbacks);
2447             mAdapter.saveClient(mClient, mCallbacks);
2448         }
2449     };
2450 
2451     sendMsg(new MsgAddClient(*this, client, callbacks));
2452 }
2453 
2454 void
stopClientSessions(LocationAPI * client)2455 GnssAdapter::stopClientSessions(LocationAPI* client)
2456 {
2457     LOC_LOGD("%s]: client %p", __func__, client);
2458 
2459     /* Time-based Tracking */
2460     std::vector<LocationSessionKey> vTimeBasedTrackingClient;
2461     for (auto it : mTimeBasedTrackingSessions) {
2462         if (client == it.first.client) {
2463             vTimeBasedTrackingClient.emplace_back(it.first.client, it.first.id);
2464         }
2465     }
2466     for (auto key : vTimeBasedTrackingClient) {
2467         stopTimeBasedTrackingMultiplex(key.client, key.id);
2468         eraseTrackingSession(key.client, key.id);
2469     }
2470 
2471     /* Distance-based Tracking */
2472     for (auto it = mDistanceBasedTrackingSessions.begin();
2473               it != mDistanceBasedTrackingSessions.end(); /* no increment here*/) {
2474         if (client == it->first.client) {
2475             mLocApi->stopDistanceBasedTracking(it->first.id, new LocApiResponse(*getContext(),
2476                           [this, client, id=it->first.id] (LocationError err) {
2477                     if (LOCATION_ERROR_SUCCESS == err) {
2478                         eraseTrackingSession(client, id);
2479                     }
2480                 }
2481             ));
2482         }
2483         ++it; // increment only when not erasing an iterator
2484     }
2485 
2486 }
2487 
2488 void
updateClientsEventMask()2489 GnssAdapter::updateClientsEventMask()
2490 {
2491     // need to register for leap second info
2492     // for proper nmea generation
2493     LOC_API_ADAPTER_EVENT_MASK_T mask = LOC_API_ADAPTER_BIT_LOC_SYSTEM_INFO |
2494             LOC_API_ADAPTER_BIT_EVENT_REPORT_INFO;
2495     for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
2496         if (it->second.trackingCb != nullptr ||
2497             it->second.gnssLocationInfoCb != nullptr ||
2498             it->second.engineLocationsInfoCb != nullptr) {
2499             mask |= LOC_API_ADAPTER_BIT_PARSED_POSITION_REPORT;
2500         }
2501         if (it->second.gnssSvCb != nullptr) {
2502             mask |= LOC_API_ADAPTER_BIT_SATELLITE_REPORT;
2503         }
2504         if ((it->second.gnssNmeaCb != nullptr) && (mNmeaMask)) {
2505             mask |= LOC_API_ADAPTER_BIT_NMEA_1HZ_REPORT;
2506         }
2507         if (it->second.gnssMeasurementsCb != nullptr) {
2508             mask |= LOC_API_ADAPTER_BIT_GNSS_MEASUREMENT;
2509         }
2510         if (it->second.gnssDataCb != nullptr) {
2511             mask |= LOC_API_ADAPTER_BIT_PARSED_POSITION_REPORT;
2512             mask |= LOC_API_ADAPTER_BIT_NMEA_1HZ_REPORT;
2513             updateNmeaMask(mNmeaMask | LOC_NMEA_MASK_DEBUG_V02);
2514         }
2515     }
2516 
2517     /*
2518     ** For Automotive use cases we need to enable MEASUREMENT, POLY and EPHEMERIS
2519     ** when QDR is enabled (e.g.: either enabled via conf file or
2520     ** engine hub is loaded successfully).
2521     ** Note: this need to be called from msg queue thread.
2522     */
2523     if((1 == ContextBase::mGps_conf.EXTERNAL_DR_ENABLED) ||
2524        (true == initEngHubProxy())) {
2525         mask |= LOC_API_ADAPTER_BIT_GNSS_MEASUREMENT;
2526         mask |= LOC_API_ADAPTER_BIT_GNSS_SV_POLYNOMIAL_REPORT;
2527         mask |= LOC_API_ADAPTER_BIT_PARSED_UNPROPAGATED_POSITION_REPORT;
2528         mask |= LOC_API_ADAPTER_BIT_GNSS_SV_EPHEMERIS_REPORT;
2529 
2530         // Nhz measurement bit is set based on callback from loc eng hub
2531         // for Nhz engines.
2532         mask |= checkMask(LOC_API_ADAPTER_BIT_GNSS_NHZ_MEASUREMENT);
2533 
2534         LOC_LOGd("Auto usecase, Enable MEAS/POLY/EPHEMERIS - mask 0x%" PRIx64 "",
2535                 mask);
2536     }
2537 
2538     if (mAgpsManager.isRegistered()) {
2539         mask |= LOC_API_ADAPTER_BIT_LOCATION_SERVER_REQUEST;
2540     }
2541     // Add ODCPI handling
2542     if (nullptr != mOdcpiRequestCb) {
2543         mask |= LOC_API_ADAPTER_BIT_REQUEST_WIFI;
2544     }
2545 
2546     // need to register for leap second info
2547     // for proper nmea generation
2548     mask |= LOC_API_ADAPTER_BIT_LOC_SYSTEM_INFO;
2549 
2550     // always register for NI NOTIFY VERIFY to handle internally in HAL
2551     mask |= LOC_API_ADAPTER_BIT_NI_NOTIFY_VERIFY_REQUEST;
2552 
2553     // Enable the latency report
2554     if (mask & LOC_API_ADAPTER_BIT_GNSS_MEASUREMENT) {
2555         if (mLogger.isLogEnabled()) {
2556             mask |= LOC_API_ADAPTER_BIT_LATENCY_INFORMATION;
2557         }
2558     }
2559 
2560     updateEvtMask(mask, LOC_REGISTRATION_MASK_SET);
2561 }
2562 
2563 void
handleEngineUpEvent()2564 GnssAdapter::handleEngineUpEvent()
2565 {
2566     LOC_LOGD("%s]: ", __func__);
2567 
2568     struct MsgHandleEngineUpEvent : public LocMsg {
2569         GnssAdapter& mAdapter;
2570         inline MsgHandleEngineUpEvent(GnssAdapter& adapter) :
2571             LocMsg(),
2572             mAdapter(adapter) {}
2573         virtual void proc() const {
2574             mAdapter.setEngineCapabilitiesKnown(true);
2575             mAdapter.broadcastCapabilities(mAdapter.getCapabilities());
2576             // must be called only after capabilities are known
2577             mAdapter.setConfig();
2578             mAdapter.gnssSvIdConfigUpdate();
2579             mAdapter.gnssSvTypeConfigUpdate();
2580             mAdapter.updateSystemPowerState(mAdapter.getSystemPowerState());
2581             mAdapter.gnssSecondaryBandConfigUpdate();
2582             // start CDFW service
2583             mAdapter.initCDFWService();
2584             // restart sessions
2585             mAdapter.restartSessions(true);
2586             for (auto msg: mAdapter.mPendingMsgs) {
2587                 mAdapter.sendMsg(msg);
2588             }
2589             mAdapter.mPendingMsgs.clear();
2590         }
2591     };
2592 
2593     readConfigCommand();
2594     sendMsg(new MsgHandleEngineUpEvent(*this));
2595 }
2596 
2597 void
restartSessions(bool modemSSR)2598 GnssAdapter::restartSessions(bool modemSSR)
2599 {
2600     LOC_LOGi(":enter");
2601 
2602     if (modemSSR) {
2603         // odcpi session is no longer active after restart
2604         mOdcpiRequestActive = false;
2605     }
2606 
2607     // SPE will be restarted now, so set this variable to false.
2608     mSPEAlreadyRunningAtHighestInterval = false;
2609 
2610     if (false == mTimeBasedTrackingSessions.empty()) {
2611         // inform engine hub that GNSS session is about to start
2612         mEngHubProxy->gnssSetFixMode(mLocPositionMode);
2613         mEngHubProxy->gnssStartFix();
2614         checkUpdateDgnssNtrip(false);
2615     }
2616 
2617     checkAndRestartSPESession();
2618 }
2619 
checkAndRestartSPESession()2620 void GnssAdapter::checkAndRestartSPESession()
2621 {
2622     LOC_LOGD("%s]: ", __func__);
2623 
2624     // SPE will be restarted now, so set this variable to false.
2625     mSPEAlreadyRunningAtHighestInterval = false;
2626 
2627     checkAndRestartTimeBasedSession();
2628 
2629     for (auto it = mDistanceBasedTrackingSessions.begin();
2630         it != mDistanceBasedTrackingSessions.end(); ++it) {
2631         mLocApi->startDistanceBasedTracking(it->first.id, it->second,
2632                                             new LocApiResponse(*getContext(),
2633                                             [] (LocationError /*err*/) {}));
2634     }
2635 }
2636 
2637 // suspend all on-going sessions
2638 void
suspendSessions()2639 GnssAdapter::suspendSessions()
2640 {
2641     LOC_LOGi(":enter");
2642 
2643     if (!mTimeBasedTrackingSessions.empty()) {
2644         // inform engine hub that GNSS session has stopped
2645         mEngHubProxy->gnssStopFix();
2646         mLocApi->stopFix(nullptr);
2647         if (isDgnssNmeaRequired()) {
2648             mDgnssState &= ~DGNSS_STATE_NO_NMEA_PENDING;
2649         }
2650         stopDgnssNtrip();
2651         mSPEAlreadyRunningAtHighestInterval = false;
2652     }
2653 }
2654 
checkAndRestartTimeBasedSession()2655 void GnssAdapter::checkAndRestartTimeBasedSession()
2656 {
2657     LOC_LOGD("%s]: ", __func__);
2658 
2659     if (!mTimeBasedTrackingSessions.empty()) {
2660         // get the LocationOptions that has the smallest interval, which should be the active one
2661         TrackingOptions smallestIntervalOptions; // size is zero until set for the first time
2662         TrackingOptions highestPowerTrackingOptions;
2663         memset(&smallestIntervalOptions, 0, sizeof(smallestIntervalOptions));
2664         memset(&highestPowerTrackingOptions, 0, sizeof(highestPowerTrackingOptions));
2665         for (auto it = mTimeBasedTrackingSessions.begin();
2666                 it != mTimeBasedTrackingSessions.end(); ++it) {
2667             // size of zero means we havent set it yet
2668             if (0 == smallestIntervalOptions.size ||
2669                 it->second.minInterval < smallestIntervalOptions.minInterval) {
2670                  smallestIntervalOptions = it->second;
2671             }
2672             GnssPowerMode powerMode = it->second.powerMode;
2673             // Size of zero means we havent set it yet
2674             if (0 == highestPowerTrackingOptions.size ||
2675                 (GNSS_POWER_MODE_INVALID != powerMode &&
2676                         powerMode < highestPowerTrackingOptions.powerMode)) {
2677                  highestPowerTrackingOptions = it->second;
2678             }
2679         }
2680 
2681         highestPowerTrackingOptions.setLocationOptions(smallestIntervalOptions);
2682         // want to run SPE session at a fixed min interval in some automotive scenarios
2683         if(!checkAndSetSPEToRunforNHz(highestPowerTrackingOptions)) {
2684             mLocApi->startTimeBasedTracking(highestPowerTrackingOptions, nullptr);
2685         }
2686     }
2687 }
2688 
2689 LocationCapabilitiesMask
getCapabilities()2690 GnssAdapter::getCapabilities()
2691 {
2692     LocationCapabilitiesMask mask = 0;
2693     uint32_t carrierCapabilities = ContextBase::getCarrierCapabilities();
2694     // time based tracking always supported
2695     mask |= LOCATION_CAPABILITIES_TIME_BASED_TRACKING_BIT;
2696     // geofence always supported
2697     mask |= LOCATION_CAPABILITIES_GEOFENCE_BIT;
2698     if (carrierCapabilities & LOC_GPS_CAPABILITY_MSB) {
2699         mask |= LOCATION_CAPABILITIES_GNSS_MSB_BIT;
2700     }
2701     if (LOC_GPS_CAPABILITY_MSA & carrierCapabilities) {
2702         mask |= LOCATION_CAPABILITIES_GNSS_MSA_BIT;
2703     }
2704     if (ContextBase::isMessageSupported(LOC_API_ADAPTER_MESSAGE_DISTANCE_BASE_LOCATION_BATCHING)) {
2705         mask |= LOCATION_CAPABILITIES_TIME_BASED_BATCHING_BIT |
2706                 LOCATION_CAPABILITIES_DISTANCE_BASED_BATCHING_BIT;
2707     }
2708     if (ContextBase::isMessageSupported(LOC_API_ADAPTER_MESSAGE_DISTANCE_BASE_TRACKING)) {
2709         mask |= LOCATION_CAPABILITIES_DISTANCE_BASED_TRACKING_BIT;
2710     }
2711     if (ContextBase::isMessageSupported(LOC_API_ADAPTER_MESSAGE_OUTDOOR_TRIP_BATCHING)) {
2712         mask |= LOCATION_CAPABILITIES_OUTDOOR_TRIP_BATCHING_BIT;
2713     }
2714     if (ContextBase::gnssConstellationConfig()) {
2715         mask |= LOCATION_CAPABILITIES_GNSS_MEASUREMENTS_BIT;
2716     }
2717     if (ContextBase::isFeatureSupported(LOC_SUPPORTED_FEATURE_DEBUG_NMEA_V02)) {
2718         mask |= LOCATION_CAPABILITIES_DEBUG_NMEA_BIT;
2719     }
2720     if (ContextBase::isFeatureSupported(LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02)) {
2721         mask |= LOCATION_CAPABILITIES_CONSTELLATION_ENABLEMENT_BIT;
2722     }
2723     if (ContextBase::isFeatureSupported(LOC_SUPPORTED_FEATURE_AGPM_V02)) {
2724         mask |= LOCATION_CAPABILITIES_AGPM_BIT;
2725     }
2726     //Get QWES feature status mask
2727     mask |= ContextBase::getQwesFeatureStatus();
2728     return mask;
2729 }
2730 
2731 void
notifyClientOfCachedLocationSystemInfo(LocationAPI * client,const LocationCallbacks & callbacks)2732 GnssAdapter::notifyClientOfCachedLocationSystemInfo(
2733         LocationAPI* client, const LocationCallbacks& callbacks) {
2734 
2735     if (mLocSystemInfo.systemInfoMask) {
2736         // client need to be notified if client has not yet previously registered
2737         // for the info but now register for it.
2738         bool notifyClientOfSystemInfo = false;
2739         // check whether we need to notify client of cached location system info
2740         //
2741         // client need to be notified if client has not yet previously registered
2742         // for the info but now register for it.
2743         if (callbacks.locationSystemInfoCb) {
2744             notifyClientOfSystemInfo = true;
2745             auto it = mClientData.find(client);
2746             if (it != mClientData.end()) {
2747                 LocationCallbacks oldCallbacks = it->second;
2748                 if (oldCallbacks.locationSystemInfoCb) {
2749                     notifyClientOfSystemInfo = false;
2750                 }
2751             }
2752         }
2753 
2754         if (notifyClientOfSystemInfo) {
2755             callbacks.locationSystemInfoCb(mLocSystemInfo);
2756         }
2757     }
2758 }
2759 
2760 bool
isTimeBasedTrackingSession(LocationAPI * client,uint32_t sessionId)2761 GnssAdapter::isTimeBasedTrackingSession(LocationAPI* client, uint32_t sessionId)
2762 {
2763     LocationSessionKey key(client, sessionId);
2764     return (mTimeBasedTrackingSessions.find(key) != mTimeBasedTrackingSessions.end());
2765 }
2766 
2767 bool
isDistanceBasedTrackingSession(LocationAPI * client,uint32_t sessionId)2768 GnssAdapter::isDistanceBasedTrackingSession(LocationAPI* client, uint32_t sessionId)
2769 {
2770     LocationSessionKey key(client, sessionId);
2771     return (mDistanceBasedTrackingSessions.find(key) != mDistanceBasedTrackingSessions.end());
2772 }
2773 
2774 bool
hasCallbacksToStartTracking(LocationAPI * client)2775 GnssAdapter::hasCallbacksToStartTracking(LocationAPI* client)
2776 {
2777     bool allowed = false;
2778     auto it = mClientData.find(client);
2779     if (it != mClientData.end()) {
2780         if (it->second.trackingCb || it->second.gnssLocationInfoCb ||
2781                 it->second.engineLocationsInfoCb || it->second.gnssMeasurementsCb ||
2782                 it->second.gnssDataCb || it->second.gnssSvCb || it->second.gnssNmeaCb) {
2783             allowed = true;
2784         } else {
2785             LOC_LOGi("missing right callback to start tracking")
2786         }
2787     } else {
2788         LOC_LOGi("client %p not found", client)
2789     }
2790     return allowed;
2791 }
2792 
2793 bool
isTrackingSession(LocationAPI * client,uint32_t sessionId)2794 GnssAdapter::isTrackingSession(LocationAPI* client, uint32_t sessionId)
2795 {
2796     LocationSessionKey key(client, sessionId);
2797     return (mTimeBasedTrackingSessions.find(key) != mTimeBasedTrackingSessions.end());
2798 }
2799 
2800 void
reportPowerStateIfChanged()2801 GnssAdapter::reportPowerStateIfChanged()
2802 {
2803     bool newPowerOn = !mTimeBasedTrackingSessions.empty() ||
2804                       !mDistanceBasedTrackingSessions.empty();
2805     if (newPowerOn != mPowerOn) {
2806         mPowerOn = newPowerOn;
2807         if (mPowerStateCb != nullptr) {
2808             mPowerStateCb(mPowerOn);
2809         }
2810     }
2811 }
2812 
2813 void
getPowerStateChangesCommand(std::function<void (bool)> powerStateCb)2814 GnssAdapter::getPowerStateChangesCommand(std::function<void(bool)> powerStateCb)
2815 {
2816     LOC_LOGD("%s]: ", __func__);
2817 
2818     struct MsgReportLocation : public LocMsg {
2819         GnssAdapter& mAdapter;
2820         std::function<void(bool)> mPowerStateCb;
2821         inline MsgReportLocation(GnssAdapter& adapter,
2822                                  std::function<void(bool)> powerStateCb) :
2823             LocMsg(),
2824             mAdapter(adapter),
2825             mPowerStateCb(powerStateCb) {}
2826         inline virtual void proc() const {
2827             mAdapter.savePowerStateCallback(mPowerStateCb);
2828             mPowerStateCb(mAdapter.getPowerState());
2829         }
2830     };
2831 
2832     sendMsg(new MsgReportLocation(*this, powerStateCb));
2833 }
2834 
2835 void
saveTrackingSession(LocationAPI * client,uint32_t sessionId,const TrackingOptions & options)2836 GnssAdapter::saveTrackingSession(LocationAPI* client, uint32_t sessionId,
2837                                 const TrackingOptions& options)
2838 {
2839     LocationSessionKey key(client, sessionId);
2840     if ((options.minDistance > 0) &&
2841             ContextBase::isMessageSupported(LOC_API_ADAPTER_MESSAGE_DISTANCE_BASE_TRACKING)) {
2842         mDistanceBasedTrackingSessions[key] = options;
2843     } else {
2844         mTimeBasedTrackingSessions[key] = options;
2845     }
2846     reportPowerStateIfChanged();
2847 }
2848 
2849 void
eraseTrackingSession(LocationAPI * client,uint32_t sessionId)2850 GnssAdapter::eraseTrackingSession(LocationAPI* client, uint32_t sessionId)
2851 {
2852     LocationSessionKey key(client, sessionId);
2853     auto it = mTimeBasedTrackingSessions.find(key);
2854     if (it != mTimeBasedTrackingSessions.end()) {
2855         mTimeBasedTrackingSessions.erase(it);
2856     } else {
2857         auto itr = mDistanceBasedTrackingSessions.find(key);
2858         if (itr != mDistanceBasedTrackingSessions.end()) {
2859             mDistanceBasedTrackingSessions.erase(itr);
2860         }
2861     }
2862     reportPowerStateIfChanged();
2863 }
2864 
setLocPositionMode(const LocPosMode & mode)2865 bool GnssAdapter::setLocPositionMode(const LocPosMode& mode) {
2866     if (!mLocPositionMode.equals(mode)) {
2867         mLocPositionMode = mode;
2868         return true;
2869     } else {
2870         return false;
2871     }
2872 }
2873 
2874 void
reportResponse(LocationAPI * client,LocationError err,uint32_t sessionId)2875 GnssAdapter::reportResponse(LocationAPI* client, LocationError err, uint32_t sessionId)
2876 {
2877     LOC_LOGD("%s]: client %p id %u err %u", __func__, client, sessionId, err);
2878 
2879     auto it = mClientData.find(client);
2880     if (it != mClientData.end() && it->second.responseCb != nullptr) {
2881         it->second.responseCb(err, sessionId);
2882     } else {
2883         LOC_LOGW("%s]: client %p id %u not found in data", __func__, client, sessionId);
2884     }
2885 }
2886 
2887 void
reportResponse(LocationError err,uint32_t sessionId)2888 GnssAdapter::reportResponse(LocationError err, uint32_t sessionId)
2889 {
2890     LOC_LOGD("%s]: id %u err %u", __func__, sessionId, err);
2891 
2892     if (mControlCallbacks.size > 0 && mControlCallbacks.responseCb != nullptr) {
2893         mControlCallbacks.responseCb(err, sessionId);
2894     } else {
2895         LOC_LOGW("%s]: control client response callback not found", __func__);
2896     }
2897 }
2898 
2899 void
reportResponse(size_t count,LocationError * errs,uint32_t * ids)2900 GnssAdapter::reportResponse(size_t count, LocationError* errs, uint32_t* ids)
2901 {
2902     IF_LOC_LOGD {
2903         std::string idsString = "[";
2904         std::string errsString = "[";
2905         if (NULL != ids && NULL != errs) {
2906             for (size_t i=0; i < count; ++i) {
2907                 idsString += std::to_string(ids[i]) + " ";
2908                 errsString += std::to_string(errs[i]) + " ";
2909             }
2910         }
2911         idsString += "]";
2912         errsString += "]";
2913 
2914         LOC_LOGD("%s]: ids %s errs %s",
2915                  __func__, idsString.c_str(), errsString.c_str());
2916     }
2917 
2918     if (mControlCallbacks.size > 0 && mControlCallbacks.collectiveResponseCb != nullptr) {
2919         mControlCallbacks.collectiveResponseCb(count, errs, ids);
2920     } else {
2921         LOC_LOGW("%s]: control client callback not found", __func__);
2922     }
2923 }
2924 
2925 uint32_t
startTrackingCommand(LocationAPI * client,TrackingOptions & options)2926 GnssAdapter::startTrackingCommand(LocationAPI* client, TrackingOptions& options)
2927 {
2928     uint32_t sessionId = generateSessionId();
2929     LOC_LOGD("%s]: client %p id %u minInterval %u minDistance %u mode %u powermode %u tbm %u",
2930              __func__, client, sessionId, options.minInterval, options.minDistance, options.mode,
2931              options.powerMode, options.tbm);
2932 
2933     struct MsgStartTracking : public LocMsg {
2934         GnssAdapter& mAdapter;
2935         LocApiBase& mApi;
2936         LocationAPI* mClient;
2937         uint32_t mSessionId;
2938         mutable TrackingOptions mOptions;
2939         inline MsgStartTracking(GnssAdapter& adapter,
2940                                LocApiBase& api,
2941                                LocationAPI* client,
2942                                uint32_t sessionId,
2943                                TrackingOptions options) :
2944             LocMsg(),
2945             mAdapter(adapter),
2946             mApi(api),
2947             mClient(client),
2948             mSessionId(sessionId),
2949             mOptions(options) {}
2950         inline virtual void proc() const {
2951             // distance based tracking will need to know engine capabilities before it can start
2952             if (!mAdapter.isEngineCapabilitiesKnown() && mOptions.minDistance > 0) {
2953                 mAdapter.mPendingMsgs.push_back(new MsgStartTracking(*this));
2954                 return;
2955             }
2956             LocationError err = LOCATION_ERROR_SUCCESS;
2957             if (!mAdapter.hasCallbacksToStartTracking(mClient)) {
2958                 err = LOCATION_ERROR_CALLBACK_MISSING;
2959             } else if (0 == mOptions.size) {
2960                 err = LOCATION_ERROR_INVALID_PARAMETER;
2961             } else {
2962                 if (mOptions.minInterval < MIN_TRACKING_INTERVAL) {
2963                     mOptions.minInterval = MIN_TRACKING_INTERVAL;
2964                 }
2965                 if (mOptions.minDistance > 0 &&
2966                         ContextBase::isMessageSupported(
2967                         LOC_API_ADAPTER_MESSAGE_DISTANCE_BASE_TRACKING)) {
2968                     mAdapter.saveTrackingSession(mClient, mSessionId, mOptions);
2969                     mApi.startDistanceBasedTracking(mSessionId, mOptions,
2970                             new LocApiResponse(*mAdapter.getContext(),
2971                             [&mAdapter = mAdapter, mSessionId = mSessionId, mClient = mClient]
2972                             (LocationError err) {
2973                         if (LOCATION_ERROR_SUCCESS != err) {
2974                             mAdapter.eraseTrackingSession(mClient, mSessionId);
2975                         }
2976                         mAdapter.reportResponse(mClient, err, mSessionId);
2977                     }));
2978                 } else {
2979                     if (GNSS_POWER_MODE_M4 == mOptions.powerMode &&
2980                             mOptions.tbm > TRACKING_TBM_THRESHOLD_MILLIS) {
2981                         LOC_LOGd("TBM (%d) > %d Falling back to M2 power mode",
2982                                 mOptions.tbm, TRACKING_TBM_THRESHOLD_MILLIS);
2983                         mOptions.powerMode = GNSS_POWER_MODE_M2;
2984                     }
2985                     // Api doesn't support multiple clients for time based tracking, so mutiplex
2986                     bool reportToClientWithNoWait =
2987                             mAdapter.startTimeBasedTrackingMultiplex(mClient, mSessionId, mOptions);
2988                     mAdapter.saveTrackingSession(mClient, mSessionId, mOptions);
2989 
2990                     if (reportToClientWithNoWait) {
2991                         mAdapter.reportResponse(mClient, LOCATION_ERROR_SUCCESS, mSessionId);
2992                     }
2993                 }
2994             }
2995         }
2996     };
2997 
2998     sendMsg(new MsgStartTracking(*this, *mLocApi, client, sessionId, options));
2999     return sessionId;
3000 
3001 }
3002 
3003 bool
startTimeBasedTrackingMultiplex(LocationAPI * client,uint32_t sessionId,const TrackingOptions & options)3004 GnssAdapter::startTimeBasedTrackingMultiplex(LocationAPI* client, uint32_t sessionId,
3005                                              const TrackingOptions& options)
3006 {
3007     bool reportToClientWithNoWait = true;
3008 
3009     if (mTimeBasedTrackingSessions.empty()) {
3010         /*Reset previous NMEA reported time stamp */
3011         mPrevNmeaRptTimeNsec = 0;
3012         startTimeBasedTracking(client, sessionId, options);
3013         // need to wait for QMI callback
3014         reportToClientWithNoWait = false;
3015     } else {
3016         // find the smallest interval and powerMode
3017         TrackingOptions multiplexedOptions = {}; // size is 0 until set for the first time
3018         GnssPowerMode multiplexedPowerMode = GNSS_POWER_MODE_INVALID;
3019         memset(&multiplexedOptions, 0, sizeof(multiplexedOptions));
3020         for (auto it = mTimeBasedTrackingSessions.begin(); it != mTimeBasedTrackingSessions.end(); ++it) {
3021             // if not set or there is a new smallest interval, then set the new interval
3022             if (0 == multiplexedOptions.size ||
3023                 it->second.minInterval < multiplexedOptions.minInterval) {
3024                 multiplexedOptions = it->second;
3025             }
3026             // if session is not the one we are updating and either powerMode
3027             // is not set or there is a new smallest powerMode, then set the new powerMode
3028             if (GNSS_POWER_MODE_INVALID == multiplexedPowerMode ||
3029                 it->second.powerMode < multiplexedPowerMode) {
3030                 multiplexedPowerMode = it->second.powerMode;
3031             }
3032         }
3033         bool updateOptions = false;
3034         // if session we are starting has smaller interval then next smallest
3035         if (options.minInterval < multiplexedOptions.minInterval) {
3036             multiplexedOptions.minInterval = options.minInterval;
3037             updateOptions = true;
3038         }
3039 
3040         // if session we are starting has smaller powerMode then next smallest
3041         if (options.powerMode < multiplexedPowerMode) {
3042             multiplexedOptions.powerMode = options.powerMode;
3043             updateOptions = true;
3044         }
3045         if (updateOptions) {
3046             // restart time based tracking with the newly updated options
3047 
3048             startTimeBasedTracking(client, sessionId, multiplexedOptions);
3049             // need to wait for QMI callback
3050             reportToClientWithNoWait = false;
3051         }
3052         // else part: no QMI call is made, need to report back to client right away
3053     }
3054 
3055     return reportToClientWithNoWait;
3056 }
3057 
3058 void
startTimeBasedTracking(LocationAPI * client,uint32_t sessionId,const TrackingOptions & trackingOptions)3059 GnssAdapter::startTimeBasedTracking(LocationAPI* client, uint32_t sessionId,
3060         const TrackingOptions& trackingOptions)
3061 {
3062     LOC_LOGd("minInterval %u minDistance %u mode %u powermode %u tbm %u",
3063             trackingOptions.minInterval, trackingOptions.minDistance,
3064             trackingOptions.mode, trackingOptions.powerMode, trackingOptions.tbm);
3065     LocPosMode locPosMode = {};
3066     convertOptions(locPosMode, trackingOptions);
3067     // save position mode parameters
3068     setLocPositionMode(locPosMode);
3069     // inform engine hub that GNSS session is about to start
3070     mEngHubProxy->gnssSetFixMode(mLocPositionMode);
3071     mEngHubProxy->gnssStartFix();
3072 
3073     // want to run SPE session at a fixed min interval in some automotive scenarios
3074     // use a local copy of TrackingOptions as the TBF may get modified in the
3075     // checkAndSetSPEToRunforNHz function
3076     TrackingOptions tempOptions(trackingOptions);
3077     if (!checkAndSetSPEToRunforNHz(tempOptions)) {
3078         mLocApi->startTimeBasedTracking(tempOptions, new LocApiResponse(*getContext(),
3079                           [this, client, sessionId] (LocationError err) {
3080                 if (LOCATION_ERROR_SUCCESS != err) {
3081                     eraseTrackingSession(client, sessionId);
3082                 } else {
3083                     checkUpdateDgnssNtrip(false);
3084                 }
3085 
3086                 reportResponse(client, err, sessionId);
3087             }
3088         ));
3089     } else {
3090         reportResponse(client, LOCATION_ERROR_SUCCESS, sessionId);
3091     }
3092 
3093 }
3094 
3095 void
updateTracking(LocationAPI * client,uint32_t sessionId,const TrackingOptions & updatedOptions,const TrackingOptions & oldOptions)3096 GnssAdapter::updateTracking(LocationAPI* client, uint32_t sessionId,
3097         const TrackingOptions& updatedOptions, const TrackingOptions& oldOptions)
3098 {
3099     LocPosMode locPosMode = {};
3100     convertOptions(locPosMode, updatedOptions);
3101     // save position mode parameters
3102     setLocPositionMode(locPosMode);
3103 
3104     // inform engine hub that GNSS session is about to start
3105     mEngHubProxy->gnssSetFixMode(mLocPositionMode);
3106     mEngHubProxy->gnssStartFix();
3107 
3108     // want to run SPE session at a fixed min interval in some automotive scenarios
3109     // use a local copy of TrackingOptions as the TBF may get modified in the
3110     // checkAndSetSPEToRunforNHz function
3111     TrackingOptions tempOptions(updatedOptions);
3112     if(!checkAndSetSPEToRunforNHz(tempOptions)) {
3113         mLocApi->startTimeBasedTracking(tempOptions, new LocApiResponse(*getContext(),
3114                           [this, client, sessionId, oldOptions] (LocationError err) {
3115                 if (LOCATION_ERROR_SUCCESS != err) {
3116                     // restore the old LocationOptions
3117                     saveTrackingSession(client, sessionId, oldOptions);
3118                 }
3119                 reportResponse(client, err, sessionId);
3120             }
3121         ));
3122     } else {
3123         reportResponse(client, LOCATION_ERROR_SUCCESS, sessionId);
3124     }
3125 }
3126 
3127 void
updateTrackingOptionsCommand(LocationAPI * client,uint32_t id,TrackingOptions & options)3128 GnssAdapter::updateTrackingOptionsCommand(LocationAPI* client, uint32_t id,
3129                                           TrackingOptions& options)
3130 {
3131     LOC_LOGD("%s]: client %p id %u minInterval %u mode %u",
3132              __func__, client, id, options.minInterval, options.mode);
3133 
3134     struct MsgUpdateTracking : public LocMsg {
3135         GnssAdapter& mAdapter;
3136         LocApiBase& mApi;
3137         LocationAPI* mClient;
3138         uint32_t mSessionId;
3139         mutable TrackingOptions mOptions;
3140         inline MsgUpdateTracking(GnssAdapter& adapter,
3141                                 LocApiBase& api,
3142                                 LocationAPI* client,
3143                                 uint32_t sessionId,
3144                                 TrackingOptions options) :
3145             LocMsg(),
3146             mAdapter(adapter),
3147             mApi(api),
3148             mClient(client),
3149             mSessionId(sessionId),
3150             mOptions(options) {}
3151         inline virtual void proc() const {
3152             // distance based tracking will need to know engine capabilities before it can start
3153             if (!mAdapter.isEngineCapabilitiesKnown() && mOptions.minDistance > 0) {
3154                 mAdapter.mPendingMsgs.push_back(new MsgUpdateTracking(*this));
3155                 return;
3156             }
3157             LocationError err = LOCATION_ERROR_SUCCESS;
3158             bool isTimeBased = mAdapter.isTimeBasedTrackingSession(mClient, mSessionId);
3159             bool isDistanceBased = mAdapter.isDistanceBasedTrackingSession(mClient, mSessionId);
3160             if (!isTimeBased && !isDistanceBased) {
3161                 err = LOCATION_ERROR_ID_UNKNOWN;
3162             } else if (0 == mOptions.size) {
3163                 err = LOCATION_ERROR_INVALID_PARAMETER;
3164             }
3165             if (LOCATION_ERROR_SUCCESS != err) {
3166                 mAdapter.reportResponse(mClient, err, mSessionId);
3167             } else {
3168                 if (GNSS_POWER_MODE_M4 == mOptions.powerMode &&
3169                         mOptions.tbm > TRACKING_TBM_THRESHOLD_MILLIS) {
3170                     LOC_LOGd("TBM (%d) > %d Falling back to M2 power mode",
3171                             mOptions.tbm, TRACKING_TBM_THRESHOLD_MILLIS);
3172                     mOptions.powerMode = GNSS_POWER_MODE_M2;
3173                 }
3174                 if (mOptions.minInterval < MIN_TRACKING_INTERVAL) {
3175                     mOptions.minInterval = MIN_TRACKING_INTERVAL;
3176                 }
3177                 // Now update session as required
3178                 if (isTimeBased && mOptions.minDistance > 0) {
3179                     // switch from time based to distance based
3180                     // Api doesn't support multiple clients for time based tracking, so mutiplex
3181                     bool reportToClientWithNoWait =
3182                         mAdapter.stopTimeBasedTrackingMultiplex(mClient, mSessionId);
3183                     // erases the time based Session
3184                     mAdapter.eraseTrackingSession(mClient, mSessionId);
3185                     if (reportToClientWithNoWait) {
3186                         mAdapter.reportResponse(mClient, LOCATION_ERROR_SUCCESS, mSessionId);
3187                     }
3188                     // saves as distance based Session
3189                     mAdapter.saveTrackingSession(mClient, mSessionId, mOptions);
3190                     mApi.startDistanceBasedTracking(mSessionId, mOptions,
3191                             new LocApiResponse(*mAdapter.getContext(),
3192                                         [] (LocationError /*err*/) {}));
3193                 } else if (isDistanceBased && mOptions.minDistance == 0) {
3194                     // switch from distance based to time based
3195                     mAdapter.eraseTrackingSession(mClient, mSessionId);
3196                     mApi.stopDistanceBasedTracking(mSessionId, new LocApiResponse(
3197                             *mAdapter.getContext(),
3198                             [&mAdapter = mAdapter, mSessionId = mSessionId, mOptions = mOptions,
3199                             mClient = mClient] (LocationError /*err*/) {
3200                         // Api doesn't support multiple clients for time based tracking,
3201                         // so mutiplex
3202                         bool reportToClientWithNoWait =
3203                                 mAdapter.startTimeBasedTrackingMultiplex(mClient, mSessionId,
3204                                                                          mOptions);
3205                         mAdapter.saveTrackingSession(mClient, mSessionId, mOptions);
3206 
3207                         if (reportToClientWithNoWait) {
3208                             mAdapter.reportResponse(mClient, LOCATION_ERROR_SUCCESS, mSessionId);
3209                         }
3210                     }));
3211                 } else if (isTimeBased) {
3212                     // update time based tracking
3213                     // Api doesn't support multiple clients for time based tracking, so mutiplex
3214                     bool reportToClientWithNoWait =
3215                             mAdapter.updateTrackingMultiplex(mClient, mSessionId, mOptions);
3216                     mAdapter.saveTrackingSession(mClient, mSessionId, mOptions);
3217 
3218                     if (reportToClientWithNoWait) {
3219                         mAdapter.reportResponse(mClient, err, mSessionId);
3220                     }
3221                 } else if (isDistanceBased) {
3222                     // restart distance based tracking
3223                     mApi.stopDistanceBasedTracking(mSessionId, new LocApiResponse(
3224                             *mAdapter.getContext(),
3225                             [&mAdapter = mAdapter, mSessionId = mSessionId, mOptions = mOptions,
3226                             mClient = mClient, &mApi = mApi] (LocationError err) {
3227                         if (LOCATION_ERROR_SUCCESS == err) {
3228                             mApi.startDistanceBasedTracking(mSessionId, mOptions,
3229                                     new LocApiResponse(*mAdapter.getContext(),
3230                                     [&mAdapter, mClient, mSessionId, mOptions]
3231                                     (LocationError err) {
3232                                 if (LOCATION_ERROR_SUCCESS == err) {
3233                                     mAdapter.saveTrackingSession(mClient, mSessionId, mOptions);
3234                                 }
3235                                 mAdapter.reportResponse(mClient, err, mSessionId);
3236                             }));
3237                         }
3238                     }));
3239                 }
3240             }
3241         }
3242     };
3243 
3244     sendMsg(new MsgUpdateTracking(*this, *mLocApi, client, id, options));
3245 }
3246 
3247 bool
updateTrackingMultiplex(LocationAPI * client,uint32_t id,const TrackingOptions & trackingOptions)3248 GnssAdapter::updateTrackingMultiplex(LocationAPI* client, uint32_t id,
3249                                      const TrackingOptions& trackingOptions)
3250 {
3251     bool reportToClientWithNoWait = true;
3252 
3253     LocationSessionKey key(client, id);
3254     // get the session we are updating
3255     auto it = mTimeBasedTrackingSessions.find(key);
3256 
3257     // cache the clients existing LocationOptions
3258     TrackingOptions oldOptions = it->second;
3259 
3260     // if session we are updating exists and the minInterval or powerMode has changed
3261     if (it != mTimeBasedTrackingSessions.end() &&
3262        (it->second.minInterval != trackingOptions.minInterval ||
3263         it->second.powerMode != trackingOptions.powerMode)) {
3264         // find the smallest interval and powerMode, other than the session we are updating
3265         TrackingOptions multiplexedOptions = {}; // size is 0 until set for the first time
3266         GnssPowerMode multiplexedPowerMode = GNSS_POWER_MODE_INVALID;
3267         memset(&multiplexedOptions, 0, sizeof(multiplexedOptions));
3268         for (auto it2 = mTimeBasedTrackingSessions.begin();
3269              it2 != mTimeBasedTrackingSessions.end(); ++it2) {
3270             // if session is not the one we are updating and either interval
3271             // is not set or there is a new smallest interval, then set the new interval
3272             if (it2->first != key && (0 == multiplexedOptions.size ||
3273                 it2->second.minInterval < multiplexedOptions.minInterval)) {
3274                  multiplexedOptions = it2->second;
3275             }
3276             // if session is not the one we are updating and either powerMode
3277             // is not set or there is a new smallest powerMode, then set the new powerMode
3278             if (it2->first != key && (GNSS_POWER_MODE_INVALID == multiplexedPowerMode ||
3279                 it2->second.powerMode < multiplexedPowerMode)) {
3280                 multiplexedPowerMode = it2->second.powerMode;
3281             }
3282             // else part: no QMI call is made, need to report back to client right away
3283         }
3284         bool updateOptions = false;
3285         // if session we are updating has smaller interval then next smallest
3286         if (trackingOptions.minInterval < multiplexedOptions.minInterval) {
3287             multiplexedOptions.minInterval = trackingOptions.minInterval;
3288             updateOptions = true;
3289         }
3290         // if session we are updating has smaller powerMode then next smallest
3291         if (trackingOptions.powerMode < multiplexedPowerMode) {
3292             multiplexedOptions.powerMode = trackingOptions.powerMode;
3293             updateOptions = true;
3294         }
3295         // if only one session exists, then tracking should be updated with it
3296         if (1 == mTimeBasedTrackingSessions.size()) {
3297             multiplexedOptions = trackingOptions;
3298             updateOptions = true;
3299         }
3300         if (updateOptions) {
3301             // restart time based tracking with the newly updated options
3302             updateTracking(client, id, multiplexedOptions, oldOptions);
3303             // need to wait for QMI callback
3304             reportToClientWithNoWait = false;
3305         }
3306     }
3307 
3308     return reportToClientWithNoWait;
3309 }
3310 
3311 void
stopTrackingCommand(LocationAPI * client,uint32_t id)3312 GnssAdapter::stopTrackingCommand(LocationAPI* client, uint32_t id)
3313 {
3314     LOC_LOGD("%s]: client %p id %u", __func__, client, id);
3315 
3316     struct MsgStopTracking : public LocMsg {
3317         GnssAdapter& mAdapter;
3318         LocApiBase& mApi;
3319         LocationAPI* mClient;
3320         uint32_t mSessionId;
3321         inline MsgStopTracking(GnssAdapter& adapter,
3322                                LocApiBase& api,
3323                                LocationAPI* client,
3324                                uint32_t sessionId) :
3325             LocMsg(),
3326             mAdapter(adapter),
3327             mApi(api),
3328             mClient(client),
3329             mSessionId(sessionId) {}
3330         inline virtual void proc() const {
3331             bool isTimeBased = mAdapter.isTimeBasedTrackingSession(mClient, mSessionId);
3332             bool isDistanceBased = mAdapter.isDistanceBasedTrackingSession(mClient, mSessionId);
3333             if (isTimeBased || isDistanceBased) {
3334                 if (isTimeBased) {
3335                     // Api doesn't support multiple clients for time based tracking, so mutiplex
3336                     bool reportToClientWithNoWait =
3337                         mAdapter.stopTimeBasedTrackingMultiplex(mClient, mSessionId);
3338                     mAdapter.eraseTrackingSession(mClient, mSessionId);
3339 
3340                     if (reportToClientWithNoWait) {
3341                         mAdapter.reportResponse(mClient, LOCATION_ERROR_SUCCESS, mSessionId);
3342                     }
3343                 } else if (isDistanceBased) {
3344                     mApi.stopDistanceBasedTracking(mSessionId, new LocApiResponse(
3345                             *mAdapter.getContext(),
3346                             [&mAdapter = mAdapter, mSessionId = mSessionId, mClient = mClient]
3347                             (LocationError err) {
3348                         if (LOCATION_ERROR_SUCCESS == err) {
3349                             mAdapter.eraseTrackingSession(mClient, mSessionId);
3350                         }
3351                         mAdapter.reportResponse(mClient, err, mSessionId);
3352                     }));
3353                 }
3354             } else {
3355                 mAdapter.reportResponse(mClient, LOCATION_ERROR_ID_UNKNOWN, mSessionId);
3356             }
3357 
3358         }
3359     };
3360 
3361     sendMsg(new MsgStopTracking(*this, *mLocApi, client, id));
3362 }
3363 
3364 bool
stopTimeBasedTrackingMultiplex(LocationAPI * client,uint32_t id)3365 GnssAdapter::stopTimeBasedTrackingMultiplex(LocationAPI* client, uint32_t id)
3366 {
3367     bool reportToClientWithNoWait = true;
3368 
3369     if (1 == mTimeBasedTrackingSessions.size()) {
3370         stopTracking(client, id);
3371         // need to wait for QMI callback
3372         reportToClientWithNoWait = false;
3373     } else {
3374         LocationSessionKey key(client, id);
3375 
3376         // get the session we are stopping
3377         auto it = mTimeBasedTrackingSessions.find(key);
3378         if (it != mTimeBasedTrackingSessions.end()) {
3379             // find the smallest interval and powerMode, other than the session we are stopping
3380             TrackingOptions multiplexedOptions = {}; // size is 0 until set for the first time
3381             GnssPowerMode multiplexedPowerMode = GNSS_POWER_MODE_INVALID;
3382             memset(&multiplexedOptions, 0, sizeof(multiplexedOptions));
3383             for (auto it2 = mTimeBasedTrackingSessions.begin();
3384                  it2 != mTimeBasedTrackingSessions.end(); ++it2) {
3385                 // if session is not the one we are stopping and either interval
3386                 // is not set or there is a new smallest interval, then set the new interval
3387                 if (it2->first != key && (0 == multiplexedOptions.size ||
3388                     it2->second.minInterval < multiplexedOptions.minInterval)) {
3389                      multiplexedOptions = it2->second;
3390                 }
3391                 // if session is not the one we are stopping and either powerMode
3392                 // is not set or there is a new smallest powerMode, then set the new powerMode
3393                 if (it2->first != key && (GNSS_POWER_MODE_INVALID == multiplexedPowerMode ||
3394                     it2->second.powerMode < multiplexedPowerMode)) {
3395                     multiplexedPowerMode = it2->second.powerMode;
3396                 }
3397             }
3398             // if session we are stopping has smaller interval then next smallest or
3399             // if session we are stopping has smaller powerMode then next smallest
3400             if (it->second.minInterval < multiplexedOptions.minInterval ||
3401                 it->second.powerMode < multiplexedPowerMode) {
3402                 multiplexedOptions.powerMode = multiplexedPowerMode;
3403                 // restart time based tracking with the newly updated options
3404                 startTimeBasedTracking(client, id, multiplexedOptions);
3405                 // need to wait for QMI callback
3406                 reportToClientWithNoWait = false;
3407             }
3408             // else part: no QMI call is made, need to report back to client right away
3409         }
3410     }
3411     return reportToClientWithNoWait;
3412 }
3413 
3414 void
stopTracking(LocationAPI * client,uint32_t id)3415 GnssAdapter::stopTracking(LocationAPI* client, uint32_t id)
3416 {
3417     // inform engine hub that GNSS session has stopped
3418     mEngHubProxy->gnssStopFix();
3419 
3420     mLocApi->stopFix(new LocApiResponse(*getContext(),
3421                      [this, client, id] (LocationError err) {
3422         reportResponse(client, err, id);
3423     }));
3424 
3425     if (isDgnssNmeaRequired()) {
3426         mDgnssState &= ~DGNSS_STATE_NO_NMEA_PENDING;
3427     }
3428     stopDgnssNtrip();
3429 
3430     mSPEAlreadyRunningAtHighestInterval = false;
3431 }
3432 
3433 bool
hasNiNotifyCallback(LocationAPI * client)3434 GnssAdapter::hasNiNotifyCallback(LocationAPI* client)
3435 {
3436     auto it = mClientData.find(client);
3437     return (it != mClientData.end() && it->second.gnssNiCb);
3438 }
3439 
3440 void
gnssNiResponseCommand(LocationAPI * client,uint32_t id,GnssNiResponse response)3441 GnssAdapter::gnssNiResponseCommand(LocationAPI* client,
3442                                    uint32_t id,
3443                                    GnssNiResponse response)
3444 {
3445     LOC_LOGD("%s]: client %p id %u response %u", __func__, client, id, response);
3446 
3447     struct MsgGnssNiResponse : public LocMsg {
3448         GnssAdapter& mAdapter;
3449         LocationAPI* mClient;
3450         uint32_t mSessionId;
3451         GnssNiResponse mResponse;
3452         inline MsgGnssNiResponse(GnssAdapter& adapter,
3453                                  LocationAPI* client,
3454                                  uint32_t sessionId,
3455                                  GnssNiResponse response) :
3456             LocMsg(),
3457             mAdapter(adapter),
3458             mClient(client),
3459             mSessionId(sessionId),
3460             mResponse(response) {}
3461         inline virtual void proc() const {
3462             NiData& niData = mAdapter.getNiData();
3463             LocationError err = LOCATION_ERROR_SUCCESS;
3464             if (!mAdapter.hasNiNotifyCallback(mClient)) {
3465                 err = LOCATION_ERROR_ID_UNKNOWN;
3466             } else {
3467                 NiSession* pSession = NULL;
3468                 if (mSessionId == niData.sessionEs.reqID &&
3469                     NULL != niData.sessionEs.rawRequest) {
3470                     pSession = &niData.sessionEs;
3471                     // ignore any SUPL NI non-Es session if a SUPL NI ES is accepted
3472                     if (mResponse == GNSS_NI_RESPONSE_ACCEPT &&
3473                         NULL != niData.session.rawRequest) {
3474                             pthread_mutex_lock(&niData.session.tLock);
3475                             niData.session.resp = GNSS_NI_RESPONSE_IGNORE;
3476                             niData.session.respRecvd = true;
3477                             pthread_cond_signal(&niData.session.tCond);
3478                             pthread_mutex_unlock(&niData.session.tLock);
3479                     }
3480                 } else if (mSessionId == niData.session.reqID &&
3481                     NULL != niData.session.rawRequest) {
3482                     pSession = &niData.session;
3483                 }
3484 
3485                 if (pSession) {
3486                     LOC_LOGI("%s]: gnssNiResponseCommand: send user mResponse %u for id %u",
3487                              __func__, mResponse, mSessionId);
3488                     pthread_mutex_lock(&pSession->tLock);
3489                     pSession->resp = mResponse;
3490                     pSession->respRecvd = true;
3491                     pthread_cond_signal(&pSession->tCond);
3492                     pthread_mutex_unlock(&pSession->tLock);
3493                 } else {
3494                     err = LOCATION_ERROR_ID_UNKNOWN;
3495                     LOC_LOGE("%s]: gnssNiResponseCommand: id %u not an active session",
3496                              __func__, mSessionId);
3497                 }
3498             }
3499             mAdapter.reportResponse(mClient, err, mSessionId);
3500         }
3501     };
3502 
3503     sendMsg(new MsgGnssNiResponse(*this, client, id, response));
3504 
3505 }
3506 
3507 void
gnssNiResponseCommand(GnssNiResponse response,void * rawRequest)3508 GnssAdapter::gnssNiResponseCommand(GnssNiResponse response, void* rawRequest)
3509 {
3510     LOC_LOGD("%s]: response %u", __func__, response);
3511 
3512     struct MsgGnssNiResponse : public LocMsg {
3513         GnssAdapter& mAdapter;
3514         LocApiBase& mApi;
3515         const GnssNiResponse mResponse;
3516         const void* mPayload;
3517         inline MsgGnssNiResponse(GnssAdapter& adapter,
3518                                  LocApiBase& api,
3519                                  const GnssNiResponse response,
3520                                  const void* rawRequest) :
3521             LocMsg(),
3522             mAdapter(adapter),
3523             mApi(api),
3524             mResponse(response),
3525             mPayload(rawRequest) {}
3526         inline virtual ~MsgGnssNiResponse() {
3527         }
3528         inline virtual void proc() const {
3529             mApi.informNiResponse(mResponse, mPayload);
3530         }
3531     };
3532 
3533     sendMsg(new MsgGnssNiResponse(*this, *mLocApi, response, rawRequest));
3534 
3535 }
3536 
3537 uint32_t
enableCommand(LocationTechnologyType techType)3538 GnssAdapter::enableCommand(LocationTechnologyType techType)
3539 {
3540     uint32_t sessionId = generateSessionId();
3541     LOC_LOGD("%s]: id %u techType %u", __func__, sessionId, techType);
3542 
3543     struct MsgEnableGnss : public LocMsg {
3544         GnssAdapter& mAdapter;
3545         LocApiBase& mApi;
3546         ContextBase& mContext;
3547         uint32_t mSessionId;
3548         LocationTechnologyType mTechType;
3549         inline MsgEnableGnss(GnssAdapter& adapter,
3550                              LocApiBase& api,
3551                              ContextBase& context,
3552                              uint32_t sessionId,
3553                              LocationTechnologyType techType) :
3554             LocMsg(),
3555             mAdapter(adapter),
3556             mApi(api),
3557             mContext(context),
3558             mSessionId(sessionId),
3559             mTechType(techType) {}
3560         inline virtual void proc() const {
3561             LocationError err = LOCATION_ERROR_SUCCESS;
3562             uint32_t afwControlId = mAdapter.getAfwControlId();
3563             if (mTechType != LOCATION_TECHNOLOGY_TYPE_GNSS) {
3564                 err = LOCATION_ERROR_INVALID_PARAMETER;
3565             } else if (afwControlId > 0) {
3566                 err = LOCATION_ERROR_ALREADY_STARTED;
3567             } else {
3568                 mContext.modemPowerVote(true);
3569                 mAdapter.setAfwControlId(mSessionId);
3570 
3571                 GnssConfigGpsLock gpsLock = GNSS_CONFIG_GPS_LOCK_NONE;
3572                 if (mAdapter.mSupportNfwControl) {
3573                     ContextBase::mGps_conf.GPS_LOCK &= GNSS_CONFIG_GPS_LOCK_NI;
3574                     gpsLock = ContextBase::mGps_conf.GPS_LOCK;
3575                 }
3576                 mApi.sendMsg(new LocApiMsg([&mApi = mApi, gpsLock]() {
3577                     mApi.setGpsLockSync(gpsLock);
3578                 }));
3579                 mAdapter.mXtraObserver.updateLockStatus(gpsLock);
3580             }
3581             mAdapter.reportResponse(err, mSessionId);
3582         }
3583     };
3584 
3585     if (mContext != NULL) {
3586         sendMsg(new MsgEnableGnss(*this, *mLocApi, *mContext, sessionId, techType));
3587     } else {
3588         LOC_LOGE("%s]: Context is NULL", __func__);
3589     }
3590 
3591     return sessionId;
3592 }
3593 
3594 void
disableCommand(uint32_t id)3595 GnssAdapter::disableCommand(uint32_t id)
3596 {
3597     LOC_LOGD("%s]: id %u", __func__, id);
3598 
3599     struct MsgDisableGnss : public LocMsg {
3600         GnssAdapter& mAdapter;
3601         LocApiBase& mApi;
3602         ContextBase& mContext;
3603         uint32_t mSessionId;
3604         inline MsgDisableGnss(GnssAdapter& adapter,
3605                              LocApiBase& api,
3606                              ContextBase& context,
3607                              uint32_t sessionId) :
3608             LocMsg(),
3609             mAdapter(adapter),
3610             mApi(api),
3611             mContext(context),
3612             mSessionId(sessionId) {}
3613         inline virtual void proc() const {
3614             LocationError err = LOCATION_ERROR_SUCCESS;
3615             uint32_t afwControlId = mAdapter.getAfwControlId();
3616             if (afwControlId != mSessionId) {
3617                 err = LOCATION_ERROR_ID_UNKNOWN;
3618             } else {
3619                 mContext.modemPowerVote(false);
3620                 mAdapter.setAfwControlId(0);
3621 
3622                 if (mAdapter.mSupportNfwControl) {
3623                     /* We need to disable MO (AFW) */
3624                     ContextBase::mGps_conf.GPS_LOCK |= GNSS_CONFIG_GPS_LOCK_MO;
3625                 }
3626                 GnssConfigGpsLock gpsLock = ContextBase::mGps_conf.GPS_LOCK;
3627                 mApi.sendMsg(new LocApiMsg([&mApi = mApi, gpsLock]() {
3628                     mApi.setGpsLockSync(gpsLock);
3629                 }));
3630                 mAdapter.mXtraObserver.updateLockStatus(gpsLock);
3631             }
3632             mAdapter.reportResponse(err, mSessionId);
3633         }
3634     };
3635 
3636     if (mContext != NULL) {
3637         sendMsg(new MsgDisableGnss(*this, *mLocApi, *mContext, id));
3638     }
3639 
3640 }
3641 
3642 // This function computes the VRP based latitude, longitude and alittude, and
3643 // north, east and up velocity and save the result into EHubTechReport.
3644 void
computeVRPBasedLla(const UlpLocation & loc,GpsLocationExtended & locExt,const LeverArmConfigInfo & leverArmConfigInfo)3645 GnssAdapter::computeVRPBasedLla(const UlpLocation& loc, GpsLocationExtended& locExt,
3646                                 const LeverArmConfigInfo& leverArmConfigInfo) {
3647 
3648     float leverArm[3];
3649     float rollPitchYaw[3];
3650     double lla[3];
3651 
3652     uint16_t locFlags = loc.gpsLocation.flags;
3653     uint64_t locExtFlags = locExt.flags;
3654 
3655     // check for SPE fix
3656     if (!((locExtFlags & GPS_LOCATION_EXTENDED_HAS_OUTPUT_ENG_TYPE) &&
3657           (locExt.locOutputEngType == LOC_OUTPUT_ENGINE_SPE))){
3658         LOC_LOGv("not SPE fix, return");
3659         return;
3660     }
3661 
3662     // we can only do translation if we have VRP based lever ARM info
3663     LeverArmTypeMask leverArmFlags = leverArmConfigInfo.leverArmValidMask;
3664     if (!(leverArmFlags & LEVER_ARM_TYPE_GNSS_TO_VRP_BIT)) {
3665         LOC_LOGd("no VRP based lever ARM info");
3666         return;
3667     }
3668 
3669     leverArm[0] = leverArmConfigInfo.gnssToVRP.forwardOffsetMeters;
3670     leverArm[1] = leverArmConfigInfo.gnssToVRP.sidewaysOffsetMeters;
3671     leverArm[2] = leverArmConfigInfo.gnssToVRP.upOffsetMeters;
3672 
3673     if ((locFlags & LOC_GPS_LOCATION_HAS_LAT_LONG) &&
3674         (locFlags & LOC_GPS_LOCATION_HAS_ALTITUDE) &&
3675         (locFlags & LOCATION_HAS_BEARING_BIT)) {
3676 
3677         lla[0] = loc.gpsLocation.latitude * DEG2RAD;
3678         lla[1] = loc.gpsLocation.longitude * DEG2RAD;
3679         lla[2] = loc.gpsLocation.altitude;
3680 
3681         rollPitchYaw[0] = 0.0f;
3682         rollPitchYaw[1] = 0.0f;
3683         rollPitchYaw[2] = loc.gpsLocation.bearing * DEG2RAD;
3684 
3685         loc_convert_lla_gnss_to_vrp(lla, rollPitchYaw, leverArm);
3686 
3687         // assign the converted value into position report and
3688         // set up valid mask
3689         locExt.llaVRPBased.latitude  = lla[0] * RAD2DEG;
3690         locExt.llaVRPBased.longitude = lla[1] * RAD2DEG;
3691         locExt.llaVRPBased.altitude  = lla[2];
3692         locExt.flags |= GPS_LOCATION_EXTENDED_HAS_LLA_VRP_BASED;
3693     } else {
3694         LOC_LOGd("SPE fix missing latitude/longitude/alitutde");
3695         return;
3696     }
3697 }
3698 
3699 void
reportPositionEvent(const UlpLocation & ulpLocation,const GpsLocationExtended & locationExtended,enum loc_sess_status status,LocPosTechMask techMask,GnssDataNotification * pDataNotify,int msInWeek)3700 GnssAdapter::reportPositionEvent(const UlpLocation& ulpLocation,
3701                                  const GpsLocationExtended& locationExtended,
3702                                  enum loc_sess_status status,
3703                                  LocPosTechMask techMask,
3704                                  GnssDataNotification* pDataNotify,
3705                                  int msInWeek)
3706 {
3707     // this position is from QMI LOC API, then send report to engine hub
3708     // also, send out SPE fix promptly to the clients that have registered
3709     // with SPE report
3710     LOC_LOGd("reportPositionEvent, eng type: %d, unpro %d, sess status %d msInWeek %d",
3711              locationExtended.locOutputEngType,
3712              ulpLocation.unpropagatedPosition, status, msInWeek);
3713 
3714     struct MsgReportSPEPosition : public LocMsg {
3715         GnssAdapter& mAdapter;
3716         mutable UlpLocation mUlpLocation;
3717         mutable GpsLocationExtended mLocationExtended;
3718         enum loc_sess_status mStatus;
3719         LocPosTechMask mTechMask;
3720         mutable GnssDataNotification mDataNotify;
3721         int mMsInWeek;
3722 
3723         inline MsgReportSPEPosition(GnssAdapter& adapter,
3724                                     const UlpLocation& ulpLocation,
3725                                     const GpsLocationExtended& locationExtended,
3726                                     enum loc_sess_status status,
3727                                     LocPosTechMask techMask,
3728                                     GnssDataNotification dataNotify,
3729                                     int msInWeek) :
3730             LocMsg(),
3731             mAdapter(adapter),
3732             mUlpLocation(ulpLocation),
3733             mLocationExtended(locationExtended),
3734             mStatus(status),
3735             mTechMask(techMask),
3736             mDataNotify(dataNotify),
3737             mMsInWeek(msInWeek) {}
3738         inline virtual void proc() const {
3739             if (mAdapter.mTimeBasedTrackingSessions.empty() &&
3740                 mAdapter.mDistanceBasedTrackingSessions.empty()) {
3741                 LOC_LOGd("reportPositionEvent, no session on-going, throw away the SPE reports");
3742                 return;
3743             }
3744 
3745             if (false == mUlpLocation.unpropagatedPosition && mDataNotify.size != 0) {
3746                 if (mMsInWeek >= 0) {
3747                     mAdapter.getDataInformation((GnssDataNotification&)mDataNotify,
3748                                                 mMsInWeek);
3749                 }
3750                 mAdapter.reportData(mDataNotify);
3751             }
3752 
3753             if (true == mAdapter.initEngHubProxy()){
3754                 // send the SPE fix to engine hub
3755                 mAdapter.mEngHubProxy->gnssReportPosition(mUlpLocation, mLocationExtended, mStatus);
3756                 // report out all SPE fix if it is not propagated, even for failed fix
3757                 if (false == mUlpLocation.unpropagatedPosition) {
3758                     EngineLocationInfo engLocationInfo = {};
3759                     engLocationInfo.location = mUlpLocation;
3760                     engLocationInfo.locationExtended = mLocationExtended;
3761                     engLocationInfo.sessionStatus = mStatus;
3762 
3763                     // obtain the VRP based latitude/longitude/altitude for SPE fix
3764                     computeVRPBasedLla(engLocationInfo.location,
3765                                        engLocationInfo.locationExtended,
3766                                        mAdapter.mLocConfigInfo.leverArmConfigInfo);
3767                     mAdapter.reportEnginePositions(1, &engLocationInfo);
3768                 }
3769                 return;
3770             }
3771 
3772             // unpropagated report: is only for engine hub to consume and no need
3773             // to send out to the clients
3774             if (true == mUlpLocation.unpropagatedPosition) {
3775                 return;
3776             }
3777 
3778             // extract bug report info - this returns true if consumed by systemstatus
3779             SystemStatus* s = mAdapter.getSystemStatus();
3780             if ((nullptr != s) &&
3781                     ((LOC_SESS_SUCCESS == mStatus) || (LOC_SESS_INTERMEDIATE == mStatus))){
3782                 s->eventPosition(mUlpLocation, mLocationExtended);
3783             }
3784 
3785             mAdapter.reportPosition(mUlpLocation, mLocationExtended, mStatus, mTechMask);
3786         }
3787     };
3788 
3789     if (mContext != NULL) {
3790         GnssDataNotification dataNotifyCopy = {};
3791         if (pDataNotify) {
3792             dataNotifyCopy = *pDataNotify;
3793             dataNotifyCopy.size = sizeof(dataNotifyCopy);
3794         }
3795         sendMsg(new MsgReportSPEPosition(*this, ulpLocation, locationExtended,
3796                                           status, techMask, dataNotifyCopy, msInWeek));
3797     }
3798 }
3799 
3800 void
reportEnginePositionsEvent(unsigned int count,EngineLocationInfo * locationArr)3801 GnssAdapter::reportEnginePositionsEvent(unsigned int count,
3802                                         EngineLocationInfo* locationArr)
3803 {
3804     struct MsgReportEnginePositions : public LocMsg {
3805         GnssAdapter& mAdapter;
3806         unsigned int mCount;
3807         EngineLocationInfo mEngLocInfo[LOC_OUTPUT_ENGINE_COUNT];
3808         inline MsgReportEnginePositions(GnssAdapter& adapter,
3809                                         unsigned int count,
3810                                         EngineLocationInfo* locationArr) :
3811             LocMsg(),
3812             mAdapter(adapter),
3813             mCount(count) {
3814             if (mCount > LOC_OUTPUT_ENGINE_COUNT) {
3815                 mCount = LOC_OUTPUT_ENGINE_COUNT;
3816             }
3817             if (mCount > 0) {
3818                 memcpy(mEngLocInfo, locationArr, sizeof(EngineLocationInfo)*mCount);
3819             }
3820         }
3821         inline virtual void proc() const {
3822             mAdapter.reportEnginePositions(mCount, mEngLocInfo);
3823         }
3824     };
3825 
3826     sendMsg(new MsgReportEnginePositions(*this, count, locationArr));
3827 }
3828 
3829 bool
needReportForGnssClient(const UlpLocation & ulpLocation,enum loc_sess_status status,LocPosTechMask techMask)3830 GnssAdapter::needReportForGnssClient(const UlpLocation& ulpLocation,
3831                                      enum loc_sess_status status,
3832                                      LocPosTechMask techMask) {
3833     bool reported = false;
3834 
3835     // if engine hub is enabled, aka, any of the engine services is enabled,
3836     // then always output position reported by engine hub to requesting client
3837     if (true == initEngHubProxy()) {
3838         reported = true;
3839     } else {
3840         reported = LocApiBase::needReport(ulpLocation, status, techMask);
3841     }
3842     return reported;
3843 }
3844 
3845 bool
needReportForFlpClient(enum loc_sess_status status,LocPosTechMask techMask)3846 GnssAdapter::needReportForFlpClient(enum loc_sess_status status,
3847                                     LocPosTechMask techMask) {
3848     if (((LOC_SESS_INTERMEDIATE == status) && !(techMask & LOC_POS_TECH_MASK_SENSORS) &&
3849         (!getAllowFlpNetworkFixes())) ||
3850         (LOC_SESS_FAILURE == status)) {
3851         return false;
3852     } else {
3853         return true;
3854     }
3855 }
3856 
3857 bool
isFlpClient(LocationCallbacks & locationCallbacks)3858 GnssAdapter::isFlpClient(LocationCallbacks& locationCallbacks)
3859 {
3860     return (locationCallbacks.gnssLocationInfoCb == nullptr &&
3861             locationCallbacks.gnssSvCb == nullptr &&
3862             locationCallbacks.gnssNmeaCb == nullptr &&
3863             locationCallbacks.gnssDataCb == nullptr &&
3864             locationCallbacks.gnssMeasurementsCb == nullptr);
3865 }
3866 
needToGenerateNmeaReport(const uint32_t & gpsTimeOfWeekMs,const struct timespec32_t & apTimeStamp)3867 bool GnssAdapter::needToGenerateNmeaReport(const uint32_t &gpsTimeOfWeekMs,
3868         const struct timespec32_t &apTimeStamp)
3869 {
3870     bool retVal = false;
3871     uint64_t currentTimeNsec = 0;
3872 
3873     if (NMEA_PROVIDER_AP == ContextBase::mGps_conf.NMEA_PROVIDER && !mTimeBasedTrackingSessions.empty()) {
3874         currentTimeNsec = (apTimeStamp.tv_sec * BILLION_NSEC + apTimeStamp.tv_nsec);
3875         if ((GNSS_NMEA_REPORT_RATE_NHZ == ContextBase::sNmeaReportRate) ||
3876                 (GPS_DEFAULT_FIX_INTERVAL_MS <= mLocPositionMode.min_interval)) {
3877             retVal = true;
3878         } else { /*tbf is less than 1000 milli-seconds and NMEA reporting rate is set to 1Hz */
3879             /* Always send NMEA string for first position report
3880              * Send when gpsTimeOfWeekMs is closely aligned with integer boundary
3881              */
3882             if ((0 == mPrevNmeaRptTimeNsec) ||
3883                 (0 != gpsTimeOfWeekMs) && (NMEA_MIN_THRESHOLD_MSEC >= (gpsTimeOfWeekMs % 1000))) {
3884                 retVal = true;
3885             } else {
3886                 uint64_t timeDiffMsec = ((currentTimeNsec - mPrevNmeaRptTimeNsec) / 1000000);
3887                 // Send when the delta time becomes >= 1 sec
3888                 if (NMEA_MAX_THRESHOLD_MSEC <= timeDiffMsec) {
3889                     retVal = true;
3890                 }
3891             }
3892         }
3893         if (true == retVal) {
3894             mPrevNmeaRptTimeNsec = currentTimeNsec;
3895         }
3896     }
3897     return retVal;
3898 }
3899 
3900 void
logLatencyInfo()3901 GnssAdapter::logLatencyInfo()
3902 {
3903     if (0 == mGnssLatencyInfoQueue.size()) {
3904         LOC_LOGv("mGnssLatencyInfoQueue.size is 0");
3905         return;
3906     }
3907     mGnssLatencyInfoQueue.front().hlosQtimer5 = getQTimerTickCount();
3908     if (0 == mGnssLatencyInfoQueue.front().hlosQtimer3) {
3909         /* if SPE from engine hub is not reported then hlosQtimer3 = 0, set it
3910         equal to hlosQtimer2 to make sense */
3911         LOC_LOGv("hlosQtimer3 is 0, setting it to hlosQtimer2");
3912         mGnssLatencyInfoQueue.front().hlosQtimer3 = mGnssLatencyInfoQueue.front().hlosQtimer2;
3913     }
3914     if (0 == mGnssLatencyInfoQueue.front().hlosQtimer4) {
3915         /* if PPE from engine hub is not reported then hlosQtimer4 = 0, set it
3916         equal to hlosQtimer3 to make sense */
3917         LOC_LOGv("hlosQtimer4 is 0, setting it to hlosQtimer3");
3918         mGnssLatencyInfoQueue.front().hlosQtimer4 = mGnssLatencyInfoQueue.front().hlosQtimer3;
3919     }
3920     if (mGnssLatencyInfoQueue.front().hlosQtimer4 < mGnssLatencyInfoQueue.front().hlosQtimer3) {
3921         /* hlosQtimer3 is timestamped when SPE from engine hub is reported,
3922         and hlosQtimer4 is timestamped when PPE from engine hub is reported.
3923         The order is random though, hence making sure the timestamps are sorted */
3924         LOC_LOGv("hlosQtimer4 is < hlosQtimer3, swapping them");
3925         std::swap(mGnssLatencyInfoQueue.front().hlosQtimer3,
3926                   mGnssLatencyInfoQueue.front().hlosQtimer4);
3927     }
3928     LOC_LOGv("meQtimer1=%" PRIi64 " "
3929              "meQtimer2=%" PRIi64 " "
3930              "meQtimer3=%" PRIi64 " "
3931              "peQtimer1=%" PRIi64 " "
3932              "peQtimer2=%" PRIi64 " "
3933              "peQtimer3=%" PRIi64 " "
3934              "smQtimer1=%" PRIi64 " "
3935              "smQtimer2=%" PRIi64 " "
3936              "smQtimer3=%" PRIi64 " "
3937              "locMwQtimer=%" PRIi64 " "
3938              "hlosQtimer1=%" PRIi64 " "
3939              "hlosQtimer2=%" PRIi64 " "
3940              "hlosQtimer3=%" PRIi64 " "
3941              "hlosQtimer4=%" PRIi64 " "
3942              "hlosQtimer5=%" PRIi64 " ",
3943              mGnssLatencyInfoQueue.front().meQtimer1, mGnssLatencyInfoQueue.front().meQtimer2,
3944              mGnssLatencyInfoQueue.front().meQtimer3, mGnssLatencyInfoQueue.front().peQtimer1,
3945              mGnssLatencyInfoQueue.front().peQtimer2, mGnssLatencyInfoQueue.front().peQtimer3,
3946              mGnssLatencyInfoQueue.front().smQtimer1, mGnssLatencyInfoQueue.front().smQtimer2,
3947              mGnssLatencyInfoQueue.front().smQtimer3, mGnssLatencyInfoQueue.front().locMwQtimer,
3948              mGnssLatencyInfoQueue.front().hlosQtimer1, mGnssLatencyInfoQueue.front().hlosQtimer2,
3949              mGnssLatencyInfoQueue.front().hlosQtimer3, mGnssLatencyInfoQueue.front().hlosQtimer4,
3950              mGnssLatencyInfoQueue.front().hlosQtimer5);
3951     mLogger.log(mGnssLatencyInfoQueue.front());
3952     mGnssLatencyInfoQueue.pop();
3953     LOC_LOGv("mGnssLatencyInfoQueue.size after pop=%zu", mGnssLatencyInfoQueue.size());
3954 }
3955 
3956 // only fused report (when engine hub is enabled) or
3957 // SPE report (when engine hub is disabled) will reach this function
3958 void
reportPosition(const UlpLocation & ulpLocation,const GpsLocationExtended & locationExtended,enum loc_sess_status status,LocPosTechMask techMask)3959 GnssAdapter::reportPosition(const UlpLocation& ulpLocation,
3960                             const GpsLocationExtended& locationExtended,
3961                             enum loc_sess_status status,
3962                             LocPosTechMask techMask)
3963 {
3964     bool reportToGnssClient = needReportForGnssClient(ulpLocation, status, techMask);
3965     bool reportToFlpClient = needReportForFlpClient(status, techMask);
3966 
3967     if (reportToGnssClient || reportToFlpClient) {
3968         GnssLocationInfoNotification locationInfo = {};
3969         convertLocationInfo(locationInfo, locationExtended, status);
3970         convertLocation(locationInfo.location, ulpLocation, locationExtended);
3971         logLatencyInfo();
3972         for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
3973             if ((reportToFlpClient && isFlpClient(it->second)) ||
3974                     (reportToGnssClient && !isFlpClient(it->second))) {
3975                 if (nullptr != it->second.gnssLocationInfoCb) {
3976                     it->second.gnssLocationInfoCb(locationInfo);
3977                 } else if ((nullptr != it->second.engineLocationsInfoCb) &&
3978                            (false == initEngHubProxy())) {
3979                     // if engine hub is disabled, this is SPE fix from modem
3980                     // we need to mark one copy marked as fused and one copy marked as PPE
3981                     // and dispatch it to the engineLocationsInfoCb
3982                     GnssLocationInfoNotification engLocationsInfo[2];
3983                     engLocationsInfo[0] = locationInfo;
3984                     engLocationsInfo[0].locOutputEngType = LOC_OUTPUT_ENGINE_FUSED;
3985                     engLocationsInfo[0].flags |= GNSS_LOCATION_INFO_OUTPUT_ENG_TYPE_BIT;
3986                     engLocationsInfo[1] = locationInfo;
3987                     it->second.engineLocationsInfoCb(2, engLocationsInfo);
3988                 } else if (nullptr != it->second.trackingCb) {
3989                     it->second.trackingCb(locationInfo.location);
3990                 }
3991             }
3992         }
3993 
3994         mGnssSvIdUsedInPosAvail = false;
3995         mGnssMbSvIdUsedInPosAvail = false;
3996         if (reportToGnssClient) {
3997             if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_GNSS_SV_USED_DATA) {
3998                 mGnssSvIdUsedInPosAvail = true;
3999                 mGnssSvIdUsedInPosition = locationExtended.gnss_sv_used_ids;
4000                 if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_MULTIBAND) {
4001                     mGnssMbSvIdUsedInPosAvail = true;
4002                     mGnssMbSvIdUsedInPosition = locationExtended.gnss_mb_sv_used_ids;
4003                 }
4004             }
4005 
4006             // if PACE is enabled
4007             if ((true == mLocConfigInfo.paceConfigInfo.isValid) &&
4008                 (true == mLocConfigInfo.paceConfigInfo.enable)) {
4009                 // If fix has sensor contribution, and it is fused fix with DRE engine
4010                 // contributing to the fix, inject to modem
4011                 if ((LOC_POS_TECH_MASK_SENSORS & techMask) &&
4012                         (locationInfo.flags & GNSS_LOCATION_INFO_OUTPUT_ENG_TYPE_BIT) &&
4013                         (locationInfo.locOutputEngType == LOC_OUTPUT_ENGINE_FUSED) &&
4014                         (locationInfo.flags & GNSS_LOCATION_INFO_OUTPUT_ENG_MASK_BIT) &&
4015                         (locationInfo.locOutputEngMask & DEAD_RECKONING_ENGINE)) {
4016                     mLocApi->injectPosition(locationInfo, false);
4017                 }
4018             }
4019         }
4020     }
4021 
4022     if (needToGenerateNmeaReport(locationExtended.gpsTime.gpsTimeOfWeekMs,
4023             locationExtended.timeStamp.apTimeStamp)) {
4024         /*Only BlankNMEA sentence needs to be processed and sent, if both lat, long is 0 &
4025           horReliability is not set. */
4026         bool blank_fix = ((0 == ulpLocation.gpsLocation.latitude) &&
4027                           (0 == ulpLocation.gpsLocation.longitude) &&
4028                           (LOC_RELIABILITY_NOT_SET == locationExtended.horizontal_reliability));
4029         uint8_t generate_nmea = (reportToGnssClient && status != LOC_SESS_FAILURE && !blank_fix);
4030         bool custom_nmea_gga = (1 == ContextBase::mGps_conf.CUSTOM_NMEA_GGA_FIX_QUALITY_ENABLED);
4031         bool isTagBlockGroupingEnabled =
4032                 (1 == ContextBase::mGps_conf.NMEA_TAG_BLOCK_GROUPING_ENABLED);
4033         std::vector<std::string> nmeaArraystr;
4034         int indexOfGGA = -1;
4035         loc_nmea_generate_pos(ulpLocation, locationExtended, mLocSystemInfo, generate_nmea,
4036                 custom_nmea_gga, nmeaArraystr, indexOfGGA, isTagBlockGroupingEnabled);
4037         stringstream ss;
4038         for (auto itor = nmeaArraystr.begin(); itor != nmeaArraystr.end(); ++itor) {
4039             ss << *itor;
4040         }
4041         string s = ss.str();
4042         reportNmea(s.c_str(), s.length());
4043 
4044         /* DgnssNtrip */
4045         if (-1 != indexOfGGA && isDgnssNmeaRequired()) {
4046             mDgnssState |= DGNSS_STATE_NO_NMEA_PENDING;
4047             mStartDgnssNtripParams.nmea = std::move(nmeaArraystr[indexOfGGA]);
4048             bool isLocationValid = (0 != ulpLocation.gpsLocation.latitude) ||
4049                     (0 != ulpLocation.gpsLocation.longitude);
4050             checkUpdateDgnssNtrip(isLocationValid);
4051         }
4052     }
4053 }
4054 
4055 void
reportLatencyInfoEvent(const GnssLatencyInfo & gnssLatencyInfo)4056 GnssAdapter::reportLatencyInfoEvent(const GnssLatencyInfo& gnssLatencyInfo)
4057 {
4058     struct MsgReportLatencyInfo : public LocMsg {
4059         GnssAdapter& mAdapter;
4060         GnssLatencyInfo mGnssLatencyInfo;
4061         inline MsgReportLatencyInfo(GnssAdapter& adapter,
4062             const GnssLatencyInfo& gnssLatencyInfo) :
4063             mGnssLatencyInfo(gnssLatencyInfo),
4064             mAdapter(adapter) {}
4065         inline virtual void proc() const {
4066             mAdapter.mGnssLatencyInfoQueue.push(mGnssLatencyInfo);
4067             LOC_LOGv("mGnssLatencyInfoQueue.size after push=%zu",
4068                       mAdapter.mGnssLatencyInfoQueue.size());
4069         }
4070     };
4071     sendMsg(new MsgReportLatencyInfo(*this, gnssLatencyInfo));
4072 }
4073 
4074 void
reportEnginePositions(unsigned int count,const EngineLocationInfo * locationArr)4075 GnssAdapter::reportEnginePositions(unsigned int count,
4076                                    const EngineLocationInfo* locationArr)
4077 {
4078     bool needReportEnginePositions = false;
4079     for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
4080         if (nullptr != it->second.engineLocationsInfoCb) {
4081             needReportEnginePositions = true;
4082             break;
4083         }
4084     }
4085 
4086     GnssLocationInfoNotification locationInfo[LOC_OUTPUT_ENGINE_COUNT] = {};
4087     for (unsigned int i = 0; i < count; i++) {
4088         const EngineLocationInfo* engLocation = (locationArr+i);
4089         // if it is fused/default location, call reportPosition maintain legacy behavior
4090         if ((GPS_LOCATION_EXTENDED_HAS_OUTPUT_ENG_TYPE & engLocation->locationExtended.flags) &&
4091             (LOC_OUTPUT_ENGINE_FUSED == engLocation->locationExtended.locOutputEngType)) {
4092             reportPosition(engLocation->location,
4093                            engLocation->locationExtended,
4094                            engLocation->sessionStatus,
4095                            engLocation->location.tech_mask);
4096         }
4097 
4098         if (needReportEnginePositions) {
4099             convertLocationInfo(locationInfo[i], engLocation->locationExtended,
4100                                 engLocation->sessionStatus);
4101             convertLocation(locationInfo[i].location,
4102                             engLocation->location,
4103                             engLocation->locationExtended);
4104         }
4105     }
4106 
4107     const EngineLocationInfo* engLocation = locationArr;
4108     LOC_LOGv("engLocation->locationExtended.locOutputEngType=%d",
4109              engLocation->locationExtended.locOutputEngType);
4110 
4111     if (0 != mGnssLatencyInfoQueue.size()) {
4112         if ((GPS_LOCATION_EXTENDED_HAS_OUTPUT_ENG_TYPE & engLocation->locationExtended.flags) &&
4113             (LOC_OUTPUT_ENGINE_SPE == engLocation->locationExtended.locOutputEngType)) {
4114             mGnssLatencyInfoQueue.front().hlosQtimer3 = getQTimerTickCount();
4115             LOC_LOGv("SPE hlosQtimer3=%" PRIi64 " ", mGnssLatencyInfoQueue.front().hlosQtimer3);
4116         }
4117         if ((GPS_LOCATION_EXTENDED_HAS_OUTPUT_ENG_TYPE & engLocation->locationExtended.flags) &&
4118             (LOC_OUTPUT_ENGINE_PPE == engLocation->locationExtended.locOutputEngType)) {
4119             mGnssLatencyInfoQueue.front().hlosQtimer4 = getQTimerTickCount();
4120             LOC_LOGv("PPE hlosQtimer4=%" PRIi64 " ", mGnssLatencyInfoQueue.front().hlosQtimer4);
4121         }
4122     }
4123     if (needReportEnginePositions) {
4124         for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
4125             if (nullptr != it->second.engineLocationsInfoCb) {
4126                 it->second.engineLocationsInfoCb(count, locationInfo);
4127             }
4128         }
4129     }
4130 }
4131 
4132 void
reportSvEvent(const GnssSvNotification & svNotify,bool fromEngineHub)4133 GnssAdapter::reportSvEvent(const GnssSvNotification& svNotify,
4134                            bool fromEngineHub)
4135 {
4136     if (!fromEngineHub) {
4137         mEngHubProxy->gnssReportSv(svNotify);
4138         if (true == initEngHubProxy()){
4139             return;
4140         }
4141     }
4142 
4143     struct MsgReportSv : public LocMsg {
4144         GnssAdapter& mAdapter;
4145         const GnssSvNotification mSvNotify;
4146         inline MsgReportSv(GnssAdapter& adapter,
4147                            const GnssSvNotification& svNotify) :
4148             LocMsg(),
4149             mAdapter(adapter),
4150             mSvNotify(svNotify) {}
4151         inline virtual void proc() const {
4152             mAdapter.reportSv((GnssSvNotification&)mSvNotify);
4153         }
4154     };
4155 
4156     sendMsg(new MsgReportSv(*this, svNotify));
4157 }
4158 
4159 void
reportSv(GnssSvNotification & svNotify)4160 GnssAdapter::reportSv(GnssSvNotification& svNotify)
4161 {
4162     int numSv = svNotify.count;
4163     uint16_t gnssSvId = 0;
4164     uint64_t svUsedIdMask = 0;
4165     for (int i=0; i < numSv; i++) {
4166         svUsedIdMask = 0;
4167         gnssSvId = svNotify.gnssSvs[i].svId;
4168         GnssSignalTypeMask signalTypeMask = svNotify.gnssSvs[i].gnssSignalTypeMask;
4169         switch (svNotify.gnssSvs[i].type) {
4170             case GNSS_SV_TYPE_GPS:
4171                 if (mGnssSvIdUsedInPosAvail) {
4172                     if (mGnssMbSvIdUsedInPosAvail) {
4173                         switch (signalTypeMask) {
4174                         case GNSS_SIGNAL_GPS_L1CA:
4175                             svUsedIdMask = mGnssMbSvIdUsedInPosition.gps_l1ca_sv_used_ids_mask;
4176                             break;
4177                         case GNSS_SIGNAL_GPS_L1C:
4178                             svUsedIdMask = mGnssMbSvIdUsedInPosition.gps_l1c_sv_used_ids_mask;
4179                             break;
4180                         case GNSS_SIGNAL_GPS_L2:
4181                             svUsedIdMask = mGnssMbSvIdUsedInPosition.gps_l2_sv_used_ids_mask;
4182                             break;
4183                         case GNSS_SIGNAL_GPS_L5:
4184                             svUsedIdMask = mGnssMbSvIdUsedInPosition.gps_l5_sv_used_ids_mask;
4185                             break;
4186                         }
4187                     } else {
4188                         svUsedIdMask = mGnssSvIdUsedInPosition.gps_sv_used_ids_mask;
4189                     }
4190                 }
4191                 break;
4192             case GNSS_SV_TYPE_GLONASS:
4193                 if (mGnssSvIdUsedInPosAvail) {
4194                     if (mGnssMbSvIdUsedInPosAvail) {
4195                         switch (signalTypeMask) {
4196                         case GNSS_SIGNAL_GLONASS_G1:
4197                             svUsedIdMask = mGnssMbSvIdUsedInPosition.glo_g1_sv_used_ids_mask;
4198                             break;
4199                         case GNSS_SIGNAL_GLONASS_G2:
4200                             svUsedIdMask = mGnssMbSvIdUsedInPosition.glo_g2_sv_used_ids_mask;
4201                             break;
4202                         }
4203                     } else {
4204                         svUsedIdMask = mGnssSvIdUsedInPosition.glo_sv_used_ids_mask;
4205                     }
4206                 }
4207                 // map the svid to respective constellation range 1..xx
4208                 // then repective constellation svUsedIdMask map correctly to svid
4209                 gnssSvId = gnssSvId - GLO_SV_PRN_MIN + 1;
4210                 break;
4211             case GNSS_SV_TYPE_BEIDOU:
4212                 if (mGnssSvIdUsedInPosAvail) {
4213                     if (mGnssMbSvIdUsedInPosAvail) {
4214                         switch (signalTypeMask) {
4215                         case GNSS_SIGNAL_BEIDOU_B1I:
4216                             svUsedIdMask = mGnssMbSvIdUsedInPosition.bds_b1i_sv_used_ids_mask;
4217                             break;
4218                         case GNSS_SIGNAL_BEIDOU_B1C:
4219                             svUsedIdMask = mGnssMbSvIdUsedInPosition.bds_b1c_sv_used_ids_mask;
4220                             break;
4221                         case GNSS_SIGNAL_BEIDOU_B2I:
4222                             svUsedIdMask = mGnssMbSvIdUsedInPosition.bds_b2i_sv_used_ids_mask;
4223                             break;
4224                         case GNSS_SIGNAL_BEIDOU_B2AI:
4225                             svUsedIdMask = mGnssMbSvIdUsedInPosition.bds_b2ai_sv_used_ids_mask;
4226                             break;
4227                         case GNSS_SIGNAL_BEIDOU_B2AQ:
4228                             svUsedIdMask = mGnssMbSvIdUsedInPosition.bds_b2aq_sv_used_ids_mask;
4229                             break;
4230                         }
4231                     } else {
4232                         svUsedIdMask = mGnssSvIdUsedInPosition.bds_sv_used_ids_mask;
4233                     }
4234                 }
4235                 gnssSvId = gnssSvId - BDS_SV_PRN_MIN + 1;
4236                 break;
4237             case GNSS_SV_TYPE_GALILEO:
4238                 if (mGnssSvIdUsedInPosAvail) {
4239                     if (mGnssMbSvIdUsedInPosAvail) {
4240                         switch (signalTypeMask) {
4241                         case GNSS_SIGNAL_GALILEO_E1:
4242                             svUsedIdMask = mGnssMbSvIdUsedInPosition.gal_e1_sv_used_ids_mask;
4243                             break;
4244                         case GNSS_SIGNAL_GALILEO_E5A:
4245                             svUsedIdMask = mGnssMbSvIdUsedInPosition.gal_e5a_sv_used_ids_mask;
4246                             break;
4247                         case GNSS_SIGNAL_GALILEO_E5B:
4248                             svUsedIdMask = mGnssMbSvIdUsedInPosition.gal_e5b_sv_used_ids_mask;
4249                             break;
4250                         }
4251                     } else {
4252                         svUsedIdMask = mGnssSvIdUsedInPosition.gal_sv_used_ids_mask;
4253                     }
4254                 }
4255                 gnssSvId = gnssSvId - GAL_SV_PRN_MIN + 1;
4256                 break;
4257             case GNSS_SV_TYPE_QZSS:
4258                 if (mGnssSvIdUsedInPosAvail) {
4259                     if (mGnssMbSvIdUsedInPosAvail) {
4260                         switch (signalTypeMask) {
4261                         case GNSS_SIGNAL_QZSS_L1CA:
4262                             svUsedIdMask = mGnssMbSvIdUsedInPosition.qzss_l1ca_sv_used_ids_mask;
4263                             break;
4264                         case GNSS_SIGNAL_QZSS_L1S:
4265                             svUsedIdMask = mGnssMbSvIdUsedInPosition.qzss_l1s_sv_used_ids_mask;
4266                             break;
4267                         case GNSS_SIGNAL_QZSS_L2:
4268                             svUsedIdMask = mGnssMbSvIdUsedInPosition.qzss_l2_sv_used_ids_mask;
4269                             break;
4270                         case GNSS_SIGNAL_QZSS_L5:
4271                             svUsedIdMask = mGnssMbSvIdUsedInPosition.qzss_l5_sv_used_ids_mask;
4272                             break;
4273                         }
4274                     } else {
4275                         svUsedIdMask = mGnssSvIdUsedInPosition.qzss_sv_used_ids_mask;
4276                     }
4277                 }
4278                 gnssSvId = gnssSvId - QZSS_SV_PRN_MIN + 1;
4279                 break;
4280             case GNSS_SV_TYPE_NAVIC:
4281                 if (mGnssSvIdUsedInPosAvail) {
4282                     svUsedIdMask = mGnssSvIdUsedInPosition.navic_sv_used_ids_mask;
4283                 }
4284                 gnssSvId = gnssSvId - NAVIC_SV_PRN_MIN + 1;
4285                 break;
4286             default:
4287                 svUsedIdMask = 0;
4288                 break;
4289         }
4290 
4291         // If SV ID was used in previous position fix, then set USED_IN_FIX
4292         // flag, else clear the USED_IN_FIX flag.
4293         if (svFitsMask(svUsedIdMask, gnssSvId) && (svUsedIdMask & (1ULL << (gnssSvId - 1)))) {
4294             svNotify.gnssSvs[i].gnssSvOptionsMask |= GNSS_SV_OPTIONS_USED_IN_FIX_BIT;
4295         }
4296     }
4297 
4298     for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
4299         if (nullptr != it->second.gnssSvCb) {
4300             it->second.gnssSvCb(svNotify);
4301         }
4302     }
4303 
4304     if (NMEA_PROVIDER_AP == ContextBase::mGps_conf.NMEA_PROVIDER &&
4305         !mTimeBasedTrackingSessions.empty()) {
4306         std::vector<std::string> nmeaArraystr;
4307         loc_nmea_generate_sv(svNotify, nmeaArraystr);
4308         stringstream ss;
4309         for (auto itor = nmeaArraystr.begin(); itor != nmeaArraystr.end(); ++itor) {
4310             ss << *itor;
4311         }
4312         string s = ss.str();
4313         reportNmea(s.c_str(), s.length());
4314     }
4315 
4316     mGnssSvIdUsedInPosAvail = false;
4317     mGnssMbSvIdUsedInPosAvail = false;
4318 }
4319 
4320 void
reportNmeaEvent(const char * nmea,size_t length)4321 GnssAdapter::reportNmeaEvent(const char* nmea, size_t length)
4322 {
4323     if (NMEA_PROVIDER_AP == ContextBase::mGps_conf.NMEA_PROVIDER &&
4324         !loc_nmea_is_debug(nmea, length)) {
4325         return;
4326     }
4327 
4328     struct MsgReportNmea : public LocMsg {
4329         GnssAdapter& mAdapter;
4330         const char* mNmea;
4331         size_t mLength;
4332         inline MsgReportNmea(GnssAdapter& adapter,
4333                              const char* nmea,
4334                              size_t length) :
4335             LocMsg(),
4336             mAdapter(adapter),
4337             mNmea(new char[length+1]),
4338             mLength(length) {
4339                 if (mNmea == nullptr) {
4340                     LOC_LOGE("%s] new allocation failed, fatal error.", __func__);
4341                     return;
4342                 }
4343                 strlcpy((char*)mNmea, nmea, length+1);
4344             }
4345         inline virtual ~MsgReportNmea()
4346         {
4347             delete[] mNmea;
4348         }
4349         inline virtual void proc() const {
4350             // extract bug report info - this returns true if consumed by systemstatus
4351             bool ret = false;
4352             SystemStatus* s = mAdapter.getSystemStatus();
4353             if (nullptr != s) {
4354                 ret = s->setNmeaString(mNmea, mLength);
4355             }
4356             if (false == ret) {
4357                 // forward NMEA message to upper layer
4358                 mAdapter.reportNmea(mNmea, mLength);
4359                 // DgnssNtrip
4360                 mAdapter.reportGGAToNtrip(mNmea);
4361             }
4362         }
4363     };
4364 
4365     sendMsg(new MsgReportNmea(*this, nmea, length));
4366 }
4367 
4368 void
reportNmea(const char * nmea,size_t length)4369 GnssAdapter::reportNmea(const char* nmea, size_t length)
4370 {
4371     GnssNmeaNotification nmeaNotification = {};
4372     nmeaNotification.size = sizeof(GnssNmeaNotification);
4373 
4374     struct timeval tv;
4375     gettimeofday(&tv, (struct timezone *) NULL);
4376     int64_t now = tv.tv_sec * 1000LL + tv.tv_usec / 1000;
4377     nmeaNotification.timestamp = now;
4378     nmeaNotification.nmea = nmea;
4379     nmeaNotification.length = length;
4380 
4381     for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
4382         if (nullptr != it->second.gnssNmeaCb) {
4383             it->second.gnssNmeaCb(nmeaNotification);
4384         }
4385     }
4386 
4387     if (isNMEAPrintEnabled()) {
4388         LOC_LOGd("[%" PRId64 ", %zu] %s", now, length, nmea);
4389     }
4390 }
4391 
4392 void
reportDataEvent(const GnssDataNotification & dataNotify,int msInWeek)4393 GnssAdapter::reportDataEvent(const GnssDataNotification& dataNotify,
4394                              int msInWeek)
4395 {
4396     struct MsgReportData : public LocMsg {
4397         GnssAdapter& mAdapter;
4398         GnssDataNotification mDataNotify;
4399         int mMsInWeek;
4400         inline MsgReportData(GnssAdapter& adapter,
4401                              const GnssDataNotification& dataNotify,
4402                              int msInWeek) :
4403             LocMsg(),
4404             mAdapter(adapter),
4405             mDataNotify(dataNotify),
4406             mMsInWeek(msInWeek) {
4407         }
4408         inline virtual void proc() const {
4409             if (mMsInWeek >= 0) {
4410                 mAdapter.getDataInformation((GnssDataNotification&)mDataNotify,
4411                                             mMsInWeek);
4412             }
4413             mAdapter.reportData((GnssDataNotification&)mDataNotify);
4414         }
4415     };
4416 
4417     sendMsg(new MsgReportData(*this, dataNotify, msInWeek));
4418 }
4419 
4420 void
reportData(GnssDataNotification & dataNotify)4421 GnssAdapter::reportData(GnssDataNotification& dataNotify)
4422 {
4423     for (int sig = 0; sig < GNSS_LOC_MAX_NUMBER_OF_SIGNAL_TYPES; sig++) {
4424         if (GNSS_LOC_DATA_JAMMER_IND_BIT ==
4425             (dataNotify.gnssDataMask[sig] & GNSS_LOC_DATA_JAMMER_IND_BIT)) {
4426             LOC_LOGv("jammerInd[%d]=%f", sig, dataNotify.jammerInd[sig]);
4427         }
4428         if (GNSS_LOC_DATA_AGC_BIT ==
4429             (dataNotify.gnssDataMask[sig] & GNSS_LOC_DATA_AGC_BIT)) {
4430             LOC_LOGv("agc[%d]=%f", sig, dataNotify.agc[sig]);
4431         }
4432     }
4433     for (auto it = mClientData.begin(); it != mClientData.end(); ++it) {
4434         if (nullptr != it->second.gnssDataCb) {
4435             it->second.gnssDataCb(dataNotify);
4436         }
4437     }
4438 }
4439 
4440 bool
requestNiNotifyEvent(const GnssNiNotification & notify,const void * data,const LocInEmergency emergencyState)4441 GnssAdapter::requestNiNotifyEvent(const GnssNiNotification &notify, const void* data,
4442                                   const LocInEmergency emergencyState)
4443 {
4444     LOC_LOGI("%s]: notif_type: %d, timeout: %d, default_resp: %d"
4445              "requestor_id: %s (encoding: %d) text: %s text (encoding: %d) extras: %s",
4446              __func__, notify.type, notify.timeout, notify.timeoutResponse,
4447              notify.requestor, notify.requestorEncoding,
4448              notify.message, notify.messageEncoding, notify.extras);
4449 
4450     struct MsgReportNiNotify : public LocMsg {
4451         GnssAdapter& mAdapter;
4452         LocApiBase& mApi;
4453         const GnssNiNotification mNotify;
4454         const void* mData;
4455         const LocInEmergency mEmergencyState;
4456         inline MsgReportNiNotify(GnssAdapter& adapter,
4457                                  LocApiBase& api,
4458                                  const GnssNiNotification& notify,
4459                                  const void* data,
4460                                  const LocInEmergency emergencyState) :
4461             LocMsg(),
4462             mAdapter(adapter),
4463             mApi(api),
4464             mNotify(notify),
4465             mData(data),
4466             mEmergencyState(emergencyState) {}
4467         inline virtual void proc() const {
4468             bool bIsInEmergency = false;
4469             bool bInformNiAccept = false;
4470 
4471             bIsInEmergency = ((LOC_IN_EMERGENCY_UNKNOWN == mEmergencyState) &&
4472                     mAdapter.getE911State()) ||                // older modems
4473                     (LOC_IN_EMERGENCY_SET == mEmergencyState); // newer modems
4474 
4475             if ((mAdapter.mSupportNfwControl || 0 == mAdapter.getAfwControlId()) &&
4476                 (GNSS_NI_TYPE_SUPL == mNotify.type || GNSS_NI_TYPE_EMERGENCY_SUPL == mNotify.type)
4477                 && !bIsInEmergency &&
4478                 !(GNSS_NI_OPTIONS_PRIVACY_OVERRIDE_BIT & mNotify.options) &&
4479                 (GNSS_CONFIG_GPS_LOCK_NI & ContextBase::mGps_conf.GPS_LOCK) &&
4480                 1 == ContextBase::mGps_conf.NI_SUPL_DENY_ON_NFW_LOCKED) {
4481                 /* If all these conditions are TRUE, then deny the NI Request:
4482                 -'Q' Lock behavior OR 'P' Lock behavior and GNSS is Locked
4483                 -NI SUPL Request type or NI SUPL Emergency Request type
4484                 -NOT in an Emergency Call Session
4485                 -NOT Privacy Override option
4486                 -NFW is locked and config item NI_SUPL_DENY_ON_NFW_LOCKED = 1 */
4487                 mApi.informNiResponse(GNSS_NI_RESPONSE_DENY, mData);
4488             } else if (GNSS_NI_TYPE_EMERGENCY_SUPL == mNotify.type) {
4489                 bInformNiAccept = bIsInEmergency ||
4490                         (GNSS_CONFIG_SUPL_EMERGENCY_SERVICES_NO == ContextBase::mGps_conf.SUPL_ES);
4491 
4492                 if (bInformNiAccept) {
4493                     mAdapter.requestNiNotify(mNotify, mData, bInformNiAccept);
4494                 } else {
4495                     mApi.informNiResponse(GNSS_NI_RESPONSE_DENY, mData);
4496                 }
4497             } else if (GNSS_NI_TYPE_CONTROL_PLANE == mNotify.type) {
4498                 if (bIsInEmergency && (1 == ContextBase::mGps_conf.CP_MTLR_ES)) {
4499                     mApi.informNiResponse(GNSS_NI_RESPONSE_ACCEPT, mData);
4500                 }
4501                 else {
4502                     mAdapter.requestNiNotify(mNotify, mData, false);
4503                 }
4504             } else {
4505                 mAdapter.requestNiNotify(mNotify, mData, false);
4506             }
4507         }
4508     };
4509 
4510     sendMsg(new MsgReportNiNotify(*this, *mLocApi, notify, data, emergencyState));
4511 
4512     return true;
4513 }
4514 
4515 void
reportLocationSystemInfoEvent(const LocationSystemInfo & locationSystemInfo)4516 GnssAdapter::reportLocationSystemInfoEvent(const LocationSystemInfo & locationSystemInfo) {
4517 
4518     // send system info to engine hub
4519     mEngHubProxy->gnssReportSystemInfo(locationSystemInfo);
4520 
4521     struct MsgLocationSystemInfo : public LocMsg {
4522         GnssAdapter& mAdapter;
4523         LocationSystemInfo mSystemInfo;
4524         inline MsgLocationSystemInfo(GnssAdapter& adapter,
4525             const LocationSystemInfo& systemInfo) :
4526             LocMsg(),
4527             mAdapter(adapter),
4528             mSystemInfo(systemInfo) {}
4529         inline virtual void proc() const {
4530             mAdapter.reportLocationSystemInfo(mSystemInfo);
4531         }
4532     };
4533 
4534     sendMsg(new MsgLocationSystemInfo(*this, locationSystemInfo));
4535 }
4536 
4537 void
reportLocationSystemInfo(const LocationSystemInfo & locationSystemInfo)4538 GnssAdapter::reportLocationSystemInfo(const LocationSystemInfo & locationSystemInfo) {
4539     // save the info into the master copy piece by piece, as other system info
4540     // may come at different time
4541     if (locationSystemInfo.systemInfoMask & LOCATION_SYS_INFO_LEAP_SECOND) {
4542         mLocSystemInfo.systemInfoMask |= LOCATION_SYS_INFO_LEAP_SECOND;
4543 
4544         const LeapSecondSystemInfo &srcLeapSecondSysInfo = locationSystemInfo.leapSecondSysInfo;
4545         LeapSecondSystemInfo &dstLeapSecondSysInfo = mLocSystemInfo.leapSecondSysInfo;
4546         if (srcLeapSecondSysInfo.leapSecondInfoMask &
4547                 LEAP_SECOND_SYS_INFO_CURRENT_LEAP_SECONDS_BIT) {
4548             dstLeapSecondSysInfo.leapSecondInfoMask |=
4549                 LEAP_SECOND_SYS_INFO_CURRENT_LEAP_SECONDS_BIT;
4550             dstLeapSecondSysInfo.leapSecondCurrent = srcLeapSecondSysInfo.leapSecondCurrent;
4551         }
4552         // once leap second change event is complete, modem may send up event invalidate the leap
4553         // second change info while AP is still processing report during leap second transition
4554         // so, we choose to keep this info around even though it is old
4555         if (srcLeapSecondSysInfo.leapSecondInfoMask & LEAP_SECOND_SYS_INFO_LEAP_SECOND_CHANGE_BIT) {
4556             dstLeapSecondSysInfo.leapSecondInfoMask |= LEAP_SECOND_SYS_INFO_LEAP_SECOND_CHANGE_BIT;
4557             dstLeapSecondSysInfo.leapSecondChangeInfo = srcLeapSecondSysInfo.leapSecondChangeInfo;
4558         }
4559     }
4560 
4561     // we received new info, inform client of the newly received info
4562     if (locationSystemInfo.systemInfoMask) {
4563         for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
4564             if (it->second.locationSystemInfoCb != nullptr) {
4565                 it->second.locationSystemInfoCb(locationSystemInfo);
4566             }
4567         }
4568     }
4569 }
4570 
niThreadProc(void * args)4571 static void* niThreadProc(void *args)
4572 {
4573     NiSession* pSession = (NiSession*)args;
4574     int rc = 0;          /* return code from pthread calls */
4575 
4576     struct timespec present_time;
4577     struct timespec expire_time;
4578 
4579     pthread_mutex_lock(&pSession->tLock);
4580     /* Calculate absolute expire time */
4581     clock_gettime(CLOCK_MONOTONIC, &present_time);
4582     expire_time.tv_sec  = present_time.tv_sec + pSession->respTimeLeft;
4583     expire_time.tv_nsec = present_time.tv_nsec;
4584     LOC_LOGD("%s]: time out set for abs time %ld with delay %d sec",
4585              __func__, (long)expire_time.tv_sec, pSession->respTimeLeft);
4586 
4587     while (!pSession->respRecvd) {
4588         rc = pthread_cond_timedwait(&pSession->tCond,
4589                                     &pSession->tLock,
4590                                     &expire_time);
4591         if (rc == ETIMEDOUT) {
4592             pSession->resp = GNSS_NI_RESPONSE_NO_RESPONSE;
4593             LOC_LOGD("%s]: time out after valting for specified time. Ret Val %d",
4594                      __func__, rc);
4595             break;
4596         }
4597     }
4598     LOC_LOGD("%s]: Java layer has sent us a user response and return value from "
4599              "pthread_cond_timedwait = %d pSession->resp is %u", __func__, rc, pSession->resp);
4600     pSession->respRecvd = false; /* Reset the user response flag for the next session*/
4601 
4602     // adding this check to support modem restart, in which case, we need the thread
4603     // to exit without calling sending data. We made sure that rawRequest is NULL in
4604     // loc_eng_ni_reset_on_engine_restart()
4605     GnssAdapter* adapter = pSession->adapter;
4606     GnssNiResponse resp;
4607     void* rawRequest = NULL;
4608     bool sendResponse = false;
4609 
4610     if (NULL != pSession->rawRequest) {
4611         if (pSession->resp != GNSS_NI_RESPONSE_IGNORE) {
4612             resp = pSession->resp;
4613             rawRequest = pSession->rawRequest;
4614             sendResponse = true;
4615         } else {
4616             free(pSession->rawRequest);
4617         }
4618         pSession->rawRequest = NULL;
4619     }
4620     pthread_mutex_unlock(&pSession->tLock);
4621 
4622     pSession->respTimeLeft = 0;
4623     pSession->reqID = 0;
4624 
4625     if (sendResponse) {
4626         adapter->gnssNiResponseCommand(resp, rawRequest);
4627     }
4628 
4629     return NULL;
4630 }
4631 
4632 bool
requestNiNotify(const GnssNiNotification & notify,const void * data,const bool bInformNiAccept)4633 GnssAdapter::requestNiNotify(const GnssNiNotification& notify, const void* data,
4634                              const bool bInformNiAccept)
4635 {
4636     NiSession* pSession = NULL;
4637     gnssNiCallback gnssNiCb = nullptr;
4638 
4639     for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
4640         if (nullptr != it->second.gnssNiCb) {
4641             gnssNiCb = it->second.gnssNiCb;
4642             break;
4643         }
4644     }
4645     if (nullptr == gnssNiCb) {
4646         if (GNSS_NI_TYPE_EMERGENCY_SUPL == notify.type) {
4647             if (bInformNiAccept) {
4648                 mLocApi->informNiResponse(GNSS_NI_RESPONSE_ACCEPT, data);
4649                 NiData& niData = getNiData();
4650                 // ignore any SUPL NI non-Es session if a SUPL NI ES is accepted
4651                 if (NULL != niData.session.rawRequest) {
4652                     pthread_mutex_lock(&niData.session.tLock);
4653                     niData.session.resp = GNSS_NI_RESPONSE_IGNORE;
4654                     niData.session.respRecvd = true;
4655                     pthread_cond_signal(&niData.session.tCond);
4656                     pthread_mutex_unlock(&niData.session.tLock);
4657                 }
4658             }
4659         }
4660         EXIT_LOG(%s, "no clients with gnssNiCb.");
4661         return false;
4662     }
4663 
4664     if (notify.type == GNSS_NI_TYPE_EMERGENCY_SUPL) {
4665         if (NULL != mNiData.sessionEs.rawRequest) {
4666             LOC_LOGI("%s]: supl es NI in progress, new supl es NI ignored, type: %d",
4667                      __func__, notify.type);
4668             if (NULL != data) {
4669                 free((void*)data);
4670             }
4671         } else {
4672             pSession = &mNiData.sessionEs;
4673         }
4674     } else {
4675         if (NULL != mNiData.session.rawRequest ||
4676             NULL != mNiData.sessionEs.rawRequest) {
4677             LOC_LOGI("%s]: supl NI in progress, new supl NI ignored, type: %d",
4678                      __func__, notify.type);
4679             if (NULL != data) {
4680                 free((void*)data);
4681             }
4682         } else {
4683             pSession = &mNiData.session;
4684         }
4685     }
4686 
4687     if (pSession) {
4688         /* Save request */
4689         pSession->rawRequest = (void*)data;
4690         pSession->reqID = ++mNiData.reqIDCounter;
4691         pSession->adapter = this;
4692 
4693         int sessionId = pSession->reqID;
4694 
4695         /* For robustness, spawn a thread at this point to timeout to clear up the notification
4696          * status, even though the OEM layer in java does not do so.
4697          **/
4698         pSession->respTimeLeft =
4699              5 + (notify.timeout != 0 ? notify.timeout : LOC_NI_NO_RESPONSE_TIME);
4700 
4701         int rc = 0;
4702         rc = pthread_create(&pSession->thread, NULL, niThreadProc, pSession);
4703         if (rc) {
4704             LOC_LOGE("%s]: Loc NI thread is not created.", __func__);
4705         }
4706         rc = pthread_detach(pSession->thread);
4707         if (rc) {
4708             LOC_LOGE("%s]: Loc NI thread is not detached.", __func__);
4709         }
4710 
4711         if (nullptr != gnssNiCb) {
4712             gnssNiCb(sessionId, notify);
4713         }
4714     }
4715 
4716     return true;
4717 }
4718 
4719 void
reportGnssMeasurementsEvent(const GnssMeasurements & gnssMeasurements,int msInWeek)4720 GnssAdapter::reportGnssMeasurementsEvent(const GnssMeasurements& gnssMeasurements,
4721                                             int msInWeek)
4722 {
4723     LOC_LOGD("%s]: msInWeek=%d", __func__, msInWeek);
4724 
4725     if (0 != gnssMeasurements.gnssMeasNotification.count) {
4726         struct MsgReportGnssMeasurementData : public LocMsg {
4727             GnssAdapter& mAdapter;
4728             GnssMeasurements mGnssMeasurements;
4729             GnssMeasurementsNotification mMeasurementsNotify;
4730             inline MsgReportGnssMeasurementData(GnssAdapter& adapter,
4731                                                 const GnssMeasurements& gnssMeasurements,
4732                                                 int msInWeek) :
4733                     LocMsg(),
4734                     mAdapter(adapter),
4735                     mMeasurementsNotify(gnssMeasurements.gnssMeasNotification) {
4736                 if (-1 != msInWeek) {
4737                     mAdapter.getAgcInformation(mMeasurementsNotify, msInWeek);
4738                 }
4739             }
4740             inline virtual void proc() const {
4741                 mAdapter.reportGnssMeasurementData(mMeasurementsNotify);
4742             }
4743         };
4744 
4745         sendMsg(new MsgReportGnssMeasurementData(*this, gnssMeasurements, msInWeek));
4746     }
4747     mEngHubProxy->gnssReportSvMeasurement(gnssMeasurements.gnssSvMeasurementSet);
4748     if (mDGnssNeedReport) {
4749         reportDGnssDataUsable(gnssMeasurements.gnssSvMeasurementSet);
4750     }
4751 }
4752 
4753 void
reportGnssMeasurementData(const GnssMeasurementsNotification & measurements)4754 GnssAdapter::reportGnssMeasurementData(const GnssMeasurementsNotification& measurements)
4755 {
4756     for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
4757         if (nullptr != it->second.gnssMeasurementsCb) {
4758             it->second.gnssMeasurementsCb(measurements);
4759         }
4760     }
4761 }
4762 
4763 void
reportDGnssDataUsable(const GnssSvMeasurementSet & svMeasurementSet)4764 GnssAdapter::reportDGnssDataUsable(const GnssSvMeasurementSet &svMeasurementSet)
4765 {
4766     uint32_t i;
4767     bool preDGnssDataUsage = mDGnssDataUsage;
4768 
4769     mDGnssDataUsage = false;
4770     for (i = 0; i < svMeasurementSet.svMeasCount; i++) {
4771         const Gnss_SVMeasurementStructType& svMeas = svMeasurementSet.svMeas[i];
4772         if (svMeas.dgnssSvMeas.dgnssMeasStatus) {
4773             mDGnssDataUsage = true;
4774             break;
4775         }
4776     }
4777     if (mDGnssDataUsage != preDGnssDataUsage) {
4778         if (mCdfwInterface) {
4779             mCdfwInterface->reportUsable(mQDgnssListenerHDL, mDGnssDataUsage);
4780         }
4781     }
4782 }
4783 
4784 void
reportSvPolynomialEvent(GnssSvPolynomial & svPolynomial)4785 GnssAdapter::reportSvPolynomialEvent(GnssSvPolynomial &svPolynomial)
4786 {
4787     LOC_LOGD("%s]: ", __func__);
4788     mEngHubProxy->gnssReportSvPolynomial(svPolynomial);
4789 }
4790 
4791 void
reportSvEphemerisEvent(GnssSvEphemerisReport & svEphemeris)4792 GnssAdapter::reportSvEphemerisEvent(GnssSvEphemerisReport & svEphemeris)
4793 {
4794     LOC_LOGD("%s]:", __func__);
4795     mEngHubProxy->gnssReportSvEphemeris(svEphemeris);
4796 }
4797 
4798 
4799 bool
requestOdcpiEvent(OdcpiRequestInfo & request)4800 GnssAdapter::requestOdcpiEvent(OdcpiRequestInfo& request)
4801 {
4802     struct MsgRequestOdcpi : public LocMsg {
4803         GnssAdapter& mAdapter;
4804         OdcpiRequestInfo mOdcpiRequest;
4805         inline MsgRequestOdcpi(GnssAdapter& adapter, OdcpiRequestInfo& request) :
4806                 LocMsg(),
4807                 mAdapter(adapter),
4808                 mOdcpiRequest(request) {}
4809         inline virtual void proc() const {
4810             mAdapter.requestOdcpi(mOdcpiRequest);
4811         }
4812     };
4813 
4814     sendMsg(new MsgRequestOdcpi(*this, request));
4815     return true;
4816 }
4817 
requestOdcpi(const OdcpiRequestInfo & request)4818 void GnssAdapter::requestOdcpi(const OdcpiRequestInfo& request)
4819 {
4820     if (nullptr != mOdcpiRequestCb) {
4821         LOC_LOGd("request: type %d, tbf %d, isEmergency %d"
4822                  " requestActive: %d timerActive: %d",
4823                  request.type, request.tbfMillis, request.isEmergencyMode,
4824                  mOdcpiRequestActive, mOdcpiTimer.isActive());
4825         // ODCPI START and ODCPI STOP from modem can come in quick succession
4826         // so the mOdcpiTimer helps avoid spamming the framework as well as
4827         // extending the odcpi session past 30 seconds if needed
4828         if (ODCPI_REQUEST_TYPE_START == request.type) {
4829             if (false == mOdcpiRequestActive && false == mOdcpiTimer.isActive()) {
4830                 mOdcpiRequestCb(request);
4831                 mOdcpiRequestActive = true;
4832                 mOdcpiTimer.start();
4833             // if the current active odcpi session is non-emergency, and the new
4834             // odcpi request is emergency, replace the odcpi request with new request
4835             // and restart the timer
4836             } else if (false == mOdcpiRequest.isEmergencyMode &&
4837                        true == request.isEmergencyMode) {
4838                 mOdcpiRequestCb(request);
4839                 mOdcpiRequestActive = true;
4840                 if (true == mOdcpiTimer.isActive()) {
4841                     mOdcpiTimer.restart();
4842                 } else {
4843                     mOdcpiTimer.start();
4844                 }
4845             // if ODCPI request is not active but the timer is active, then
4846             // just update the active state and wait for timer to expire
4847             // before requesting new ODCPI to avoid spamming ODCPI requests
4848             } else if (false == mOdcpiRequestActive && true == mOdcpiTimer.isActive()) {
4849                 mOdcpiRequestActive = true;
4850             }
4851             mOdcpiRequest = request;
4852         // the request is being stopped, but allow timer to expire first
4853         // before stopping the timer just in case more ODCPI requests come
4854         // to avoid spamming more odcpi requests to the framework
4855         } else if (ODCPI_REQUEST_TYPE_STOP == request.type) {
4856             LOC_LOGd("request: type %d, isEmergency %d", request.type, request.isEmergencyMode);
4857             mOdcpiRequestCb(request);
4858             mOdcpiRequestActive = false;
4859         } else {
4860             LOC_LOGE("Invalid ODCPI request type..");
4861         }
4862     } else {
4863         LOC_LOGw("ODCPI request not supported");
4864     }
4865 }
4866 
reportDeleteAidingDataEvent(GnssAidingData & aidingData)4867 bool GnssAdapter::reportDeleteAidingDataEvent(GnssAidingData& aidingData)
4868 {
4869     LOC_LOGD("%s]:", __func__);
4870     mEngHubProxy->gnssDeleteAidingData(aidingData);
4871     return true;
4872 }
4873 
reportKlobucharIonoModelEvent(GnssKlobucharIonoModel & ionoModel)4874 bool GnssAdapter::reportKlobucharIonoModelEvent(GnssKlobucharIonoModel & ionoModel)
4875 {
4876     LOC_LOGD("%s]:", __func__);
4877     mEngHubProxy->gnssReportKlobucharIonoModel(ionoModel);
4878     return true;
4879 }
4880 
reportGnssAdditionalSystemInfoEvent(GnssAdditionalSystemInfo & additionalSystemInfo)4881 bool GnssAdapter::reportGnssAdditionalSystemInfoEvent(
4882         GnssAdditionalSystemInfo & additionalSystemInfo)
4883 {
4884     LOC_LOGD("%s]:", __func__);
4885     mEngHubProxy->gnssReportAdditionalSystemInfo(additionalSystemInfo);
4886     return true;
4887 }
4888 
reportQwesCapabilities(const std::unordered_map<LocationQwesFeatureType,bool> & featureMap)4889 bool GnssAdapter::reportQwesCapabilities(
4890         const std::unordered_map<LocationQwesFeatureType, bool> &featureMap)
4891 {
4892     struct MsgReportQwesFeatureStatus : public LocMsg {
4893         GnssAdapter& mAdapter;
4894         const std::unordered_map<LocationQwesFeatureType, bool> mFeatureMap;
4895         inline MsgReportQwesFeatureStatus(GnssAdapter& adapter,
4896                 const std::unordered_map<LocationQwesFeatureType, bool> &featureMap) :
4897             LocMsg(),
4898             mAdapter(adapter),
4899             mFeatureMap(std::move(featureMap)) {}
4900         inline virtual void proc() const {
4901             LOC_LOGi("ReportQwesFeatureStatus before caps %" PRIx64 " ",
4902                 mAdapter.getCapabilities());
4903             ContextBase::setQwesFeatureStatus(mFeatureMap);
4904             LOC_LOGi("ReportQwesFeatureStatus After caps %" PRIx64 " ",
4905                 mAdapter.getCapabilities());
4906             mAdapter.broadcastCapabilities(mAdapter.getCapabilities());
4907         }
4908     };
4909 
4910     sendMsg(new MsgReportQwesFeatureStatus(*this, featureMap));
4911     return true;
4912 }
4913 
initOdcpiCommand(const OdcpiRequestCallback & callback,OdcpiPrioritytype priority)4914 void GnssAdapter::initOdcpiCommand(const OdcpiRequestCallback& callback,
4915                                    OdcpiPrioritytype priority)
4916 {
4917     struct MsgInitOdcpi : public LocMsg {
4918         GnssAdapter& mAdapter;
4919         OdcpiRequestCallback mOdcpiCb;
4920         OdcpiPrioritytype mPriority;
4921         inline MsgInitOdcpi(GnssAdapter& adapter,
4922                 const OdcpiRequestCallback& callback,
4923                 OdcpiPrioritytype priority) :
4924                 LocMsg(),
4925                 mAdapter(adapter),
4926                 mOdcpiCb(callback), mPriority(priority){}
4927         inline virtual void proc() const {
4928             mAdapter.initOdcpi(mOdcpiCb, mPriority);
4929         }
4930     };
4931 
4932     sendMsg(new MsgInitOdcpi(*this, callback, priority));
4933 }
4934 
initOdcpi(const OdcpiRequestCallback & callback,OdcpiPrioritytype priority)4935 void GnssAdapter::initOdcpi(const OdcpiRequestCallback& callback,
4936             OdcpiPrioritytype priority)
4937 {
4938     LOC_LOGd("In priority: %d, Curr priority: %d", priority, mCallbackPriority);
4939     if (priority >= mCallbackPriority) {
4940         mOdcpiRequestCb = callback;
4941         mCallbackPriority = priority;
4942         /* Register for WIFI request */
4943         updateEvtMask(LOC_API_ADAPTER_BIT_REQUEST_WIFI,
4944                 LOC_REGISTRATION_MASK_ENABLED);
4945     }
4946 }
4947 
injectOdcpiCommand(const Location & location)4948 void GnssAdapter::injectOdcpiCommand(const Location& location)
4949 {
4950     struct MsgInjectOdcpi : public LocMsg {
4951         GnssAdapter& mAdapter;
4952         Location mLocation;
4953         inline MsgInjectOdcpi(GnssAdapter& adapter, const Location& location) :
4954                 LocMsg(),
4955                 mAdapter(adapter),
4956                 mLocation(location) {}
4957         inline virtual void proc() const {
4958             mAdapter.injectOdcpi(mLocation);
4959         }
4960     };
4961 
4962     sendMsg(new MsgInjectOdcpi(*this, location));
4963 }
4964 
injectOdcpi(const Location & location)4965 void GnssAdapter::injectOdcpi(const Location& location)
4966 {
4967     LOC_LOGd("ODCPI Injection: requestActive: %d timerActive: %d"
4968              "lat %.7f long %.7f",
4969             mOdcpiRequestActive, mOdcpiTimer.isActive(),
4970             location.latitude, location.longitude);
4971 
4972     mLocApi->injectPosition(location, true);
4973 }
4974 
4975 // Called in the context of LocTimer thread
timeOutCallback()4976 void OdcpiTimer::timeOutCallback()
4977 {
4978     if (nullptr != mAdapter) {
4979         mAdapter->odcpiTimerExpireEvent();
4980     }
4981 }
4982 
4983 // Called in the context of LocTimer thread
odcpiTimerExpireEvent()4984 void GnssAdapter::odcpiTimerExpireEvent()
4985 {
4986     struct MsgOdcpiTimerExpire : public LocMsg {
4987         GnssAdapter& mAdapter;
4988         inline MsgOdcpiTimerExpire(GnssAdapter& adapter) :
4989                 LocMsg(),
4990                 mAdapter(adapter) {}
4991         inline virtual void proc() const {
4992             mAdapter.odcpiTimerExpire();
4993         }
4994     };
4995     sendMsg(new MsgOdcpiTimerExpire(*this));
4996 }
odcpiTimerExpire()4997 void GnssAdapter::odcpiTimerExpire()
4998 {
4999     LOC_LOGd("requestActive: %d timerActive: %d",
5000             mOdcpiRequestActive, mOdcpiTimer.isActive());
5001 
5002     // if ODCPI request is still active after timer
5003     // expires, request again and restart timer
5004     if (mOdcpiRequestActive) {
5005         mOdcpiRequestCb(mOdcpiRequest);
5006         mOdcpiTimer.restart();
5007     } else {
5008         mOdcpiTimer.stop();
5009     }
5010 }
5011 
5012 void
invokeGnssEnergyConsumedCallback(uint64_t energyConsumedSinceFirstBoot)5013 GnssAdapter::invokeGnssEnergyConsumedCallback(uint64_t energyConsumedSinceFirstBoot) {
5014     if (mGnssEnergyConsumedCb) {
5015         mGnssEnergyConsumedCb(energyConsumedSinceFirstBoot);
5016         mGnssEnergyConsumedCb = nullptr;
5017     }
5018 }
5019 
5020 bool
reportGnssEngEnergyConsumedEvent(uint64_t energyConsumedSinceFirstBoot)5021 GnssAdapter::reportGnssEngEnergyConsumedEvent(uint64_t energyConsumedSinceFirstBoot){
5022     LOC_LOGD("%s]: %" PRIu64 " ", __func__, energyConsumedSinceFirstBoot);
5023 
5024     struct MsgReportGnssGnssEngEnergyConsumed : public LocMsg {
5025         GnssAdapter& mAdapter;
5026         uint64_t mGnssEnergyConsumedSinceFirstBoot;
5027         inline MsgReportGnssGnssEngEnergyConsumed(GnssAdapter& adapter,
5028                                                   uint64_t energyConsumed) :
5029                 LocMsg(),
5030                 mAdapter(adapter),
5031                 mGnssEnergyConsumedSinceFirstBoot(energyConsumed) {}
5032         inline virtual void proc() const {
5033             mAdapter.invokeGnssEnergyConsumedCallback(mGnssEnergyConsumedSinceFirstBoot);
5034         }
5035     };
5036 
5037     sendMsg(new MsgReportGnssGnssEngEnergyConsumed(*this, energyConsumedSinceFirstBoot));
5038     return true;
5039 }
5040 
initDefaultAgps()5041 void GnssAdapter::initDefaultAgps() {
5042     LOC_LOGD("%s]: ", __func__);
5043     void *handle = nullptr;
5044 
5045     LocAgpsGetAgpsCbInfo getAgpsCbInfo =
5046         (LocAgpsGetAgpsCbInfo)dlGetSymFromLib(handle, "libloc_net_iface.so",
5047             "LocNetIfaceAgps_getAgpsCbInfo");
5048     // Below step is to make sure we init nativeAgpsHandler
5049     // for Android platforms only
5050     AgpsCbInfo cbInfo = {};
5051     if (nullptr != getAgpsCbInfo) {
5052         cbInfo = getAgpsCbInfo(agpsOpenResultCb, agpsCloseResultCb, this);
5053     } else {
5054         cbInfo = mNativeAgpsHandler.getAgpsCbInfo();
5055     }
5056 
5057     if (cbInfo.statusV4Cb == nullptr) {
5058         LOC_LOGE("%s]: statusV4Cb is nullptr!", __func__);
5059         dlclose(handle);
5060         return;
5061     }
5062 
5063     initAgps(cbInfo);
5064 }
5065 
initDefaultAgpsCommand()5066 void GnssAdapter::initDefaultAgpsCommand() {
5067     LOC_LOGD("%s]: ", __func__);
5068 
5069     struct MsgInitDefaultAgps : public LocMsg {
5070         GnssAdapter& mAdapter;
5071         inline MsgInitDefaultAgps(GnssAdapter& adapter) :
5072             LocMsg(),
5073             mAdapter(adapter) {
5074             }
5075         inline virtual void proc() const {
5076             mAdapter.initDefaultAgps();
5077         }
5078     };
5079 
5080     sendMsg(new MsgInitDefaultAgps(*this));
5081 }
5082 
5083 /* INIT LOC AGPS MANAGER */
5084 
initAgps(const AgpsCbInfo & cbInfo)5085 void GnssAdapter::initAgps(const AgpsCbInfo& cbInfo) {
5086     LOC_LOGD("%s]:cbInfo.atlType - %d", __func__, cbInfo.atlType);
5087 
5088     if (!((ContextBase::mGps_conf.CAPABILITIES & LOC_GPS_CAPABILITY_MSB) ||
5089             (ContextBase::mGps_conf.CAPABILITIES & LOC_GPS_CAPABILITY_MSA))) {
5090         return;
5091     }
5092 
5093     mAgpsManager.createAgpsStateMachines(cbInfo);
5094     /* Register for AGPS event mask */
5095     updateEvtMask(LOC_API_ADAPTER_BIT_LOCATION_SERVER_REQUEST,
5096             LOC_REGISTRATION_MASK_ENABLED);
5097 }
5098 
initAgpsCommand(const AgpsCbInfo & cbInfo)5099 void GnssAdapter::initAgpsCommand(const AgpsCbInfo& cbInfo){
5100     LOC_LOGI("GnssAdapter::initAgpsCommand");
5101 
5102     /* Message to initialize AGPS module */
5103     struct AgpsMsgInit: public LocMsg {
5104         const AgpsCbInfo mCbInfo;
5105         GnssAdapter& mAdapter;
5106 
5107         inline AgpsMsgInit(const AgpsCbInfo& cbInfo,
5108                 GnssAdapter& adapter) :
5109                 LocMsg(), mCbInfo(cbInfo), mAdapter(adapter) {
5110             LOC_LOGV("AgpsMsgInit");
5111         }
5112 
5113         inline virtual void proc() const {
5114             LOC_LOGV("AgpsMsgInit::proc()");
5115             mAdapter.initAgps(mCbInfo);
5116         }
5117     };
5118 
5119     /* Send message to initialize AGPS Manager */
5120     sendMsg(new AgpsMsgInit(cbInfo, *this));
5121 }
5122 
initNfwCommand(const NfwCbInfo & cbInfo)5123 void GnssAdapter::initNfwCommand(const NfwCbInfo& cbInfo) {
5124     LOC_LOGi("GnssAdapter::initNfwCommand");
5125 
5126     /* Message to initialize NFW */
5127     struct MsgInitNfw : public LocMsg {
5128         const NfwCbInfo mCbInfo;
5129         GnssAdapter& mAdapter;
5130 
5131         inline MsgInitNfw(const NfwCbInfo& cbInfo,
5132             GnssAdapter& adapter) :
5133             LocMsg(), mCbInfo(cbInfo), mAdapter(adapter) {
5134             LOC_LOGv("MsgInitNfw");
5135         }
5136 
5137         inline virtual void proc() const {
5138             LOC_LOGv("MsgInitNfw::proc()");
5139             mAdapter.initNfw(mCbInfo);
5140         }
5141     };
5142 
5143     /* Send message to initialize NFW */
5144     sendMsg(new MsgInitNfw(cbInfo, *this));
5145 }
5146 
reportNfwNotificationEvent(GnssNfwNotification & notification)5147 void GnssAdapter::reportNfwNotificationEvent(GnssNfwNotification& notification) {
5148     LOC_LOGi("GnssAdapter::reportNfwNotificationEvent");
5149 
5150     struct MsgReportNfwNotification : public LocMsg {
5151         const GnssNfwNotification mNotification;
5152         GnssAdapter& mAdapter;
5153 
5154         inline MsgReportNfwNotification(const GnssNfwNotification& notification,
5155             GnssAdapter& adapter) :
5156             LocMsg(), mNotification(notification), mAdapter(adapter) {
5157             LOC_LOGv("MsgReportNfwNotification");
5158         }
5159 
5160         inline virtual void proc() const {
5161             LOC_LOGv("MsgReportNfwNotification::proc()");
5162             mAdapter.reportNfwNotification(mNotification);
5163         }
5164     };
5165 
5166     sendMsg(new MsgReportNfwNotification(notification, *this));
5167 }
5168 
5169 /* GnssAdapter::requestATL
5170  * Method triggered in QMI thread as part of handling below message:
5171  * eQMI_LOC_SERVER_REQUEST_OPEN_V02
5172  * Triggers the AGPS state machine to setup AGPS call for below WWAN types:
5173  * eQMI_LOC_WWAN_TYPE_INTERNET_V02
5174  * eQMI_LOC_WWAN_TYPE_AGNSS_V02
5175  * eQMI_LOC_WWAN_TYPE_AGNSS_EMERGENCY_V02 */
requestATL(int connHandle,LocAGpsType agpsType,LocApnTypeMask apnTypeMask)5176 bool GnssAdapter::requestATL(int connHandle, LocAGpsType agpsType,
5177                              LocApnTypeMask apnTypeMask){
5178 
5179     LOC_LOGI("GnssAdapter::requestATL handle=%d agpsType=0x%X apnTypeMask=0x%X",
5180         connHandle, agpsType, apnTypeMask);
5181 
5182     sendMsg( new AgpsMsgRequestATL(
5183              &mAgpsManager, connHandle, (AGpsExtType)agpsType,
5184              apnTypeMask));
5185 
5186     return true;
5187 }
5188 
5189 /* GnssAdapter::releaseATL
5190  * Method triggered in QMI thread as part of handling below message:
5191  * eQMI_LOC_SERVER_REQUEST_CLOSE_V02
5192  * Triggers teardown of an existing AGPS call */
releaseATL(int connHandle)5193 bool GnssAdapter::releaseATL(int connHandle){
5194 
5195     LOC_LOGI("GnssAdapter::releaseATL");
5196 
5197     /* Release SUPL/INTERNET/SUPL_ES ATL */
5198     struct AgpsMsgReleaseATL: public LocMsg {
5199 
5200         AgpsManager* mAgpsManager;
5201         int mConnHandle;
5202 
5203         inline AgpsMsgReleaseATL(AgpsManager* agpsManager, int connHandle) :
5204                 LocMsg(), mAgpsManager(agpsManager), mConnHandle(connHandle) {
5205 
5206             LOC_LOGV("AgpsMsgReleaseATL");
5207         }
5208 
5209         inline virtual void proc() const {
5210 
5211             LOC_LOGV("AgpsMsgReleaseATL::proc()");
5212             mAgpsManager->releaseATL(mConnHandle);
5213         }
5214     };
5215 
5216     sendMsg( new AgpsMsgReleaseATL(&mAgpsManager, connHandle));
5217 
5218     return true;
5219 }
5220 
dataConnOpenCommand(AGpsExtType agpsType,const char * apnName,int apnLen,AGpsBearerType bearerType)5221 void GnssAdapter::dataConnOpenCommand(
5222         AGpsExtType agpsType,
5223         const char* apnName, int apnLen, AGpsBearerType bearerType){
5224 
5225     LOC_LOGI("GnssAdapter::frameworkDataConnOpen");
5226 
5227     struct AgpsMsgAtlOpenSuccess: public LocMsg {
5228 
5229         AgpsManager* mAgpsManager;
5230         AGpsExtType mAgpsType;
5231         char* mApnName;
5232         int mApnLen;
5233         AGpsBearerType mBearerType;
5234 
5235         inline AgpsMsgAtlOpenSuccess(AgpsManager* agpsManager, AGpsExtType agpsType,
5236                 const char* apnName, int apnLen, AGpsBearerType bearerType) :
5237                 LocMsg(), mAgpsManager(agpsManager), mAgpsType(agpsType), mApnName(
5238                         new char[apnLen + 1]), mApnLen(apnLen), mBearerType(bearerType) {
5239 
5240             LOC_LOGV("AgpsMsgAtlOpenSuccess");
5241             if (mApnName == nullptr) {
5242                 LOC_LOGE("%s] new allocation failed, fatal error.", __func__);
5243                 // Reporting the failure here
5244                 mAgpsManager->reportAtlClosed(mAgpsType);
5245                 return;
5246             }
5247             memcpy(mApnName, apnName, apnLen);
5248             mApnName[apnLen] = 0;
5249         }
5250 
5251         inline ~AgpsMsgAtlOpenSuccess() {
5252             delete[] mApnName;
5253         }
5254 
5255         inline virtual void proc() const {
5256 
5257             LOC_LOGV("AgpsMsgAtlOpenSuccess::proc()");
5258             mAgpsManager->reportAtlOpenSuccess(mAgpsType, mApnName, mApnLen, mBearerType);
5259         }
5260     };
5261     // Added inital length checks for apnlen check to avoid security issues
5262     // In case of failure reporting the same
5263     if (NULL == apnName || apnLen > MAX_APN_LEN || (strlen(apnName) != (unsigned)apnLen)) {
5264         LOC_LOGe("%s]: incorrect apnlen length or incorrect apnName", __func__);
5265         mAgpsManager.reportAtlClosed(agpsType);
5266     } else {
5267         sendMsg( new AgpsMsgAtlOpenSuccess(
5268                     &mAgpsManager, agpsType, apnName, apnLen, bearerType));
5269     }
5270 }
5271 
dataConnClosedCommand(AGpsExtType agpsType)5272 void GnssAdapter::dataConnClosedCommand(AGpsExtType agpsType){
5273 
5274     LOC_LOGI("GnssAdapter::frameworkDataConnClosed");
5275 
5276     struct AgpsMsgAtlClosed: public LocMsg {
5277 
5278         AgpsManager* mAgpsManager;
5279         AGpsExtType mAgpsType;
5280 
5281         inline AgpsMsgAtlClosed(AgpsManager* agpsManager, AGpsExtType agpsType) :
5282                 LocMsg(), mAgpsManager(agpsManager), mAgpsType(agpsType) {
5283 
5284             LOC_LOGV("AgpsMsgAtlClosed");
5285         }
5286 
5287         inline virtual void proc() const {
5288 
5289             LOC_LOGV("AgpsMsgAtlClosed::proc()");
5290             mAgpsManager->reportAtlClosed(mAgpsType);
5291         }
5292     };
5293 
5294     sendMsg( new AgpsMsgAtlClosed(&mAgpsManager, (AGpsExtType)agpsType));
5295 }
5296 
dataConnFailedCommand(AGpsExtType agpsType)5297 void GnssAdapter::dataConnFailedCommand(AGpsExtType agpsType){
5298 
5299     LOC_LOGI("GnssAdapter::frameworkDataConnFailed");
5300 
5301     struct AgpsMsgAtlOpenFailed: public LocMsg {
5302 
5303         AgpsManager* mAgpsManager;
5304         AGpsExtType mAgpsType;
5305 
5306         inline AgpsMsgAtlOpenFailed(AgpsManager* agpsManager, AGpsExtType agpsType) :
5307                 LocMsg(), mAgpsManager(agpsManager), mAgpsType(agpsType) {
5308 
5309             LOC_LOGV("AgpsMsgAtlOpenFailed");
5310         }
5311 
5312         inline virtual void proc() const {
5313 
5314             LOC_LOGV("AgpsMsgAtlOpenFailed::proc()");
5315             mAgpsManager->reportAtlOpenFailed(mAgpsType);
5316         }
5317     };
5318 
5319     sendMsg( new AgpsMsgAtlOpenFailed(&mAgpsManager, (AGpsExtType)agpsType));
5320 }
5321 
convertSatelliteInfo(std::vector<GnssDebugSatelliteInfo> & out,const GnssSvType & in_constellation,const SystemStatusReports & in)5322 void GnssAdapter::convertSatelliteInfo(std::vector<GnssDebugSatelliteInfo>& out,
5323                                        const GnssSvType& in_constellation,
5324                                        const SystemStatusReports& in)
5325 {
5326     uint64_t sv_mask = 0ULL;
5327     uint32_t svid_min = 0;
5328     uint32_t svid_num = 0;
5329     uint32_t svid_idx = 0;
5330 
5331     uint64_t eph_health_good_mask = 0ULL;
5332     uint64_t eph_health_bad_mask = 0ULL;
5333     uint64_t server_perdiction_available_mask = 0ULL;
5334     float server_perdiction_age = 0.0f;
5335 
5336     // set constellationi based parameters
5337     switch (in_constellation) {
5338         case GNSS_SV_TYPE_GPS:
5339             svid_min = GNSS_BUGREPORT_GPS_MIN;
5340             svid_num = GPS_NUM;
5341             svid_idx = 0;
5342             if (!in.mSvHealth.empty()) {
5343                 eph_health_good_mask = in.mSvHealth.back().mGpsGoodMask;
5344                 eph_health_bad_mask  = in.mSvHealth.back().mGpsBadMask;
5345             }
5346             if (!in.mXtra.empty()) {
5347                 server_perdiction_available_mask = in.mXtra.back().mGpsXtraValid;
5348                 server_perdiction_age = (float)(in.mXtra.back().mGpsXtraAge);
5349             }
5350             break;
5351         case GNSS_SV_TYPE_GLONASS:
5352             svid_min = GNSS_BUGREPORT_GLO_MIN;
5353             svid_num = GLO_NUM;
5354             svid_idx = GPS_NUM;
5355             if (!in.mSvHealth.empty()) {
5356                 eph_health_good_mask = in.mSvHealth.back().mGloGoodMask;
5357                 eph_health_bad_mask  = in.mSvHealth.back().mGloBadMask;
5358             }
5359             if (!in.mXtra.empty()) {
5360                 server_perdiction_available_mask = in.mXtra.back().mGloXtraValid;
5361                 server_perdiction_age = (float)(in.mXtra.back().mGloXtraAge);
5362             }
5363             break;
5364         case GNSS_SV_TYPE_QZSS:
5365             svid_min = GNSS_BUGREPORT_QZSS_MIN;
5366             svid_num = QZSS_NUM;
5367             svid_idx = GPS_NUM+GLO_NUM+BDS_NUM+GAL_NUM;
5368             if (!in.mSvHealth.empty()) {
5369                 eph_health_good_mask = in.mSvHealth.back().mQzssGoodMask;
5370                 eph_health_bad_mask  = in.mSvHealth.back().mQzssBadMask;
5371             }
5372             if (!in.mXtra.empty()) {
5373                 server_perdiction_available_mask = in.mXtra.back().mQzssXtraValid;
5374                 server_perdiction_age = (float)(in.mXtra.back().mQzssXtraAge);
5375             }
5376             break;
5377         case GNSS_SV_TYPE_BEIDOU:
5378             svid_min = GNSS_BUGREPORT_BDS_MIN;
5379             svid_num = BDS_NUM;
5380             svid_idx = GPS_NUM+GLO_NUM;
5381             if (!in.mSvHealth.empty()) {
5382                 eph_health_good_mask = in.mSvHealth.back().mBdsGoodMask;
5383                 eph_health_bad_mask  = in.mSvHealth.back().mBdsBadMask;
5384             }
5385             if (!in.mXtra.empty()) {
5386                 server_perdiction_available_mask = in.mXtra.back().mBdsXtraValid;
5387                 server_perdiction_age = (float)(in.mXtra.back().mBdsXtraAge);
5388             }
5389             break;
5390         case GNSS_SV_TYPE_GALILEO:
5391             svid_min = GNSS_BUGREPORT_GAL_MIN;
5392             svid_num = GAL_NUM;
5393             svid_idx = GPS_NUM+GLO_NUM+BDS_NUM;
5394             if (!in.mSvHealth.empty()) {
5395                 eph_health_good_mask = in.mSvHealth.back().mGalGoodMask;
5396                 eph_health_bad_mask  = in.mSvHealth.back().mGalBadMask;
5397             }
5398             if (!in.mXtra.empty()) {
5399                 server_perdiction_available_mask = in.mXtra.back().mGalXtraValid;
5400                 server_perdiction_age = (float)(in.mXtra.back().mGalXtraAge);
5401             }
5402             break;
5403         case GNSS_SV_TYPE_NAVIC:
5404             svid_min = GNSS_BUGREPORT_NAVIC_MIN;
5405             svid_num = NAVIC_NUM;
5406             svid_idx = GPS_NUM+GLO_NUM+QZSS_NUM+BDS_NUM+GAL_NUM;
5407             if (!in.mSvHealth.empty()) {
5408                 eph_health_good_mask = in.mSvHealth.back().mNavicGoodMask;
5409                 eph_health_bad_mask  = in.mSvHealth.back().mNavicBadMask;
5410             }
5411             if (!in.mXtra.empty()) {
5412                 server_perdiction_available_mask = in.mXtra.back().mNavicXtraValid;
5413                 server_perdiction_age = (float)(in.mXtra.back().mNavicXtraAge);
5414             }
5415             break;
5416         default:
5417             return;
5418     }
5419 
5420     // extract each sv info from systemstatus report
5421     for(uint32_t i=0; i<svid_num && (svid_idx+i)<SV_ALL_NUM; i++) {
5422 
5423         GnssDebugSatelliteInfo s = {};
5424         s.size = sizeof(s);
5425         s.svid = i + svid_min;
5426         s.constellation = in_constellation;
5427 
5428         if (!in.mNavData.empty()) {
5429             s.mEphemerisType   = in.mNavData.back().mNav[svid_idx+i].mType;
5430             s.mEphemerisSource = in.mNavData.back().mNav[svid_idx+i].mSource;
5431         }
5432         else {
5433             s.mEphemerisType   = GNSS_EPH_TYPE_UNKNOWN;
5434             s.mEphemerisSource = GNSS_EPH_SOURCE_UNKNOWN;
5435         }
5436 
5437         sv_mask = 0x1ULL << i;
5438         if (eph_health_good_mask & sv_mask) {
5439             s.mEphemerisHealth = GNSS_EPH_HEALTH_GOOD;
5440         }
5441         else if (eph_health_bad_mask & sv_mask) {
5442             s.mEphemerisHealth = GNSS_EPH_HEALTH_BAD;
5443         }
5444         else {
5445             s.mEphemerisHealth = GNSS_EPH_HEALTH_UNKNOWN;
5446         }
5447 
5448         if (!in.mNavData.empty()) {
5449             s.ephemerisAgeSeconds =
5450                 (float)(in.mNavData.back().mNav[svid_idx+i].mAgeSec);
5451         }
5452         else {
5453             s.ephemerisAgeSeconds = 0.0f;
5454         }
5455 
5456         if (server_perdiction_available_mask & sv_mask) {
5457             s.serverPredictionIsAvailable = true;
5458         }
5459         else {
5460             s.serverPredictionIsAvailable = false;
5461         }
5462 
5463         s.serverPredictionAgeSeconds = server_perdiction_age;
5464         out.push_back(s);
5465     }
5466 
5467     return;
5468 }
5469 
getDebugReport(GnssDebugReport & r)5470 bool GnssAdapter::getDebugReport(GnssDebugReport& r)
5471 {
5472     LOC_LOGD("%s]: ", __func__);
5473 
5474     SystemStatus* systemstatus = getSystemStatus();
5475     if (nullptr == systemstatus) {
5476         return false;
5477     }
5478 
5479     SystemStatusReports reports = {};
5480     systemstatus->getReport(reports, true);
5481 
5482     r.size = sizeof(r);
5483 
5484     // location block
5485     r.mLocation.size = sizeof(r.mLocation);
5486     if(!reports.mLocation.empty() && reports.mLocation.back().mValid) {
5487         r.mLocation.mValid = true;
5488         r.mLocation.mLocation.latitude =
5489             reports.mLocation.back().mLocation.gpsLocation.latitude;
5490         r.mLocation.mLocation.longitude =
5491             reports.mLocation.back().mLocation.gpsLocation.longitude;
5492         r.mLocation.mLocation.altitude =
5493             reports.mLocation.back().mLocation.gpsLocation.altitude;
5494         r.mLocation.mLocation.speed =
5495             (double)(reports.mLocation.back().mLocation.gpsLocation.speed);
5496         r.mLocation.mLocation.bearing =
5497             (double)(reports.mLocation.back().mLocation.gpsLocation.bearing);
5498         r.mLocation.mLocation.accuracy =
5499             (double)(reports.mLocation.back().mLocation.gpsLocation.accuracy);
5500 
5501         r.mLocation.verticalAccuracyMeters =
5502             reports.mLocation.back().mLocationEx.vert_unc;
5503         r.mLocation.speedAccuracyMetersPerSecond =
5504             reports.mLocation.back().mLocationEx.speed_unc;
5505         r.mLocation.bearingAccuracyDegrees =
5506             reports.mLocation.back().mLocationEx.bearing_unc;
5507 
5508         r.mLocation.mUtcReported =
5509             reports.mLocation.back().mUtcReported;
5510     }
5511     else if(!reports.mBestPosition.empty() && reports.mBestPosition.back().mValid) {
5512         r.mLocation.mValid = true;
5513         r.mLocation.mLocation.latitude =
5514                 (double)(reports.mBestPosition.back().mBestLat) * RAD2DEG;
5515         r.mLocation.mLocation.longitude =
5516                 (double)(reports.mBestPosition.back().mBestLon) * RAD2DEG;
5517         r.mLocation.mLocation.altitude = reports.mBestPosition.back().mBestAlt;
5518         r.mLocation.mLocation.accuracy =
5519                 (double)(reports.mBestPosition.back().mBestHepe);
5520 
5521         r.mLocation.mUtcReported = reports.mBestPosition.back().mUtcReported;
5522     }
5523     else {
5524         r.mLocation.mValid = false;
5525     }
5526 
5527     if (r.mLocation.mValid) {
5528         LOC_LOGV("getDebugReport - lat=%f lon=%f alt=%f speed=%f",
5529             r.mLocation.mLocation.latitude,
5530             r.mLocation.mLocation.longitude,
5531             r.mLocation.mLocation.altitude,
5532             r.mLocation.mLocation.speed);
5533     }
5534 
5535     // time block
5536     r.mTime.size = sizeof(r.mTime);
5537     if(!reports.mTimeAndClock.empty() && reports.mTimeAndClock.back().mTimeValid) {
5538         r.mTime.mValid = true;
5539         r.mTime.timeEstimate =
5540             (((int64_t)(reports.mTimeAndClock.back().mGpsWeek)*7 +
5541                         GNSS_UTC_TIME_OFFSET)*24*60*60 -
5542               (int64_t)(reports.mTimeAndClock.back().mLeapSeconds))*1000ULL +
5543               (int64_t)(reports.mTimeAndClock.back().mGpsTowMs);
5544 
5545         if (reports.mTimeAndClock.back().mTimeUncNs > 0) {
5546             // TimeUncNs value is available
5547             r.mTime.timeUncertaintyNs =
5548                     (float)(reports.mTimeAndClock.back().mLeapSecUnc)*1000.0f +
5549                     (float)(reports.mTimeAndClock.back().mTimeUncNs);
5550         } else {
5551             // fall back to legacy TimeUnc
5552             r.mTime.timeUncertaintyNs =
5553                     ((float)(reports.mTimeAndClock.back().mTimeUnc) +
5554                      (float)(reports.mTimeAndClock.back().mLeapSecUnc))*1000.0f;
5555         }
5556 
5557         r.mTime.frequencyUncertaintyNsPerSec =
5558             (float)(reports.mTimeAndClock.back().mClockFreqBiasUnc);
5559         LOC_LOGV("getDebugReport - timeestimate=%" PRIu64 " unc=%f frequnc=%f",
5560                 r.mTime.timeEstimate,
5561                 r.mTime.timeUncertaintyNs, r.mTime.frequencyUncertaintyNsPerSec);
5562     }
5563     else {
5564         r.mTime.mValid = false;
5565     }
5566 
5567     // satellite info block
5568     convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_GPS, reports);
5569     convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_GLONASS, reports);
5570     convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_QZSS, reports);
5571     convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_BEIDOU, reports);
5572     convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_GALILEO, reports);
5573     convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_NAVIC, reports);
5574     LOC_LOGV("getDebugReport - satellite=%zu", r.mSatelliteInfo.size());
5575 
5576     return true;
5577 }
5578 
5579 /* get AGC information from system status and fill it */
5580 void
getAgcInformation(GnssMeasurementsNotification & measurements,int msInWeek)5581 GnssAdapter::getAgcInformation(GnssMeasurementsNotification& measurements, int msInWeek)
5582 {
5583     SystemStatus* systemstatus = getSystemStatus();
5584 
5585     if (nullptr != systemstatus) {
5586         SystemStatusReports reports = {};
5587         systemstatus->getReport(reports, true);
5588 
5589         if ((!reports.mRfAndParams.empty()) && (!reports.mTimeAndClock.empty()) &&
5590             (abs(msInWeek - (int)reports.mTimeAndClock.back().mGpsTowMs) < 2000)) {
5591 
5592             for (size_t i = 0; i < measurements.count; i++) {
5593                 switch (measurements.measurements[i].svType) {
5594                 case GNSS_SV_TYPE_GPS:
5595                 case GNSS_SV_TYPE_QZSS:
5596                     measurements.measurements[i].agcLevelDb =
5597                             (double)-reports.mRfAndParams.back().mJammerGps;
5598                     measurements.measurements[i].flags |=
5599                             GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT;
5600                     break;
5601 
5602                 case GNSS_SV_TYPE_GALILEO:
5603                     measurements.measurements[i].agcLevelDb =
5604                             (double)-reports.mRfAndParams.back().mJammerGal;
5605                     measurements.measurements[i].flags |=
5606                             GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT;
5607                     break;
5608 
5609                 case GNSS_SV_TYPE_GLONASS:
5610                     measurements.measurements[i].agcLevelDb =
5611                             (double)-reports.mRfAndParams.back().mJammerGlo;
5612                     measurements.measurements[i].flags |=
5613                             GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT;
5614                     break;
5615 
5616                 case GNSS_SV_TYPE_BEIDOU:
5617                     measurements.measurements[i].agcLevelDb =
5618                             (double)-reports.mRfAndParams.back().mJammerBds;
5619                     measurements.measurements[i].flags |=
5620                             GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT;
5621                     break;
5622 
5623                 case GNSS_SV_TYPE_SBAS:
5624                 case GNSS_SV_TYPE_UNKNOWN:
5625                 default:
5626                     break;
5627                 }
5628             }
5629         }
5630     }
5631 }
5632 
5633 /* get Data information from system status and fill it */
5634 void
getDataInformation(GnssDataNotification & data,int msInWeek)5635 GnssAdapter::getDataInformation(GnssDataNotification& data, int msInWeek)
5636 {
5637     SystemStatus* systemstatus = getSystemStatus();
5638 
5639     LOC_LOGV("%s]: msInWeek=%d", __func__, msInWeek);
5640     if (nullptr != systemstatus) {
5641         SystemStatusReports reports = {};
5642         systemstatus->getReport(reports, true);
5643 
5644         if ((!reports.mRfAndParams.empty()) && (!reports.mTimeAndClock.empty()) &&
5645             (abs(msInWeek - (int)reports.mTimeAndClock.back().mGpsTowMs) < 2000)) {
5646 
5647             for (int sig = GNSS_LOC_SIGNAL_TYPE_GPS_L1CA;
5648                  sig < GNSS_LOC_MAX_NUMBER_OF_SIGNAL_TYPES; sig++) {
5649                 data.gnssDataMask[sig] = 0;
5650                 data.jammerInd[sig] = 0.0;
5651                 data.agc[sig] = 0.0;
5652             }
5653             if (GNSS_INVALID_JAMMER_IND != reports.mRfAndParams.back().mJammerGps) {
5654                 data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_GPS_L1CA] |=
5655                         GNSS_LOC_DATA_AGC_BIT | GNSS_LOC_DATA_JAMMER_IND_BIT;
5656                 data.agc[GNSS_LOC_SIGNAL_TYPE_GPS_L1CA] =
5657                         (double)-reports.mRfAndParams.back().mJammerGps;
5658                 data.jammerInd[GNSS_LOC_SIGNAL_TYPE_GPS_L1CA] =
5659                         (double)reports.mRfAndParams.back().mJammerGps;
5660                 data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_QZSS_L1CA] |=
5661                         GNSS_LOC_DATA_AGC_BIT | GNSS_LOC_DATA_JAMMER_IND_BIT;
5662                 data.agc[GNSS_LOC_SIGNAL_TYPE_QZSS_L1CA] =
5663                         (double)-reports.mRfAndParams.back().mJammerGps;
5664                 data.jammerInd[GNSS_LOC_SIGNAL_TYPE_QZSS_L1CA] =
5665                         (double)reports.mRfAndParams.back().mJammerGps;
5666                 data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_SBAS_L1_CA] |=
5667                         GNSS_LOC_DATA_AGC_BIT | GNSS_LOC_DATA_JAMMER_IND_BIT;
5668                 data.agc[GNSS_LOC_SIGNAL_TYPE_SBAS_L1_CA] =
5669                         (double)-reports.mRfAndParams.back().mJammerGps;
5670                 data.jammerInd[GNSS_LOC_SIGNAL_TYPE_SBAS_L1_CA] =
5671                         (double)reports.mRfAndParams.back().mJammerGps;
5672             }
5673             if (GNSS_INVALID_JAMMER_IND != reports.mRfAndParams.back().mJammerGlo) {
5674                 data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_GLONASS_G1] |=
5675                         GNSS_LOC_DATA_AGC_BIT | GNSS_LOC_DATA_JAMMER_IND_BIT;
5676                 data.agc[GNSS_LOC_SIGNAL_TYPE_GLONASS_G1] =
5677                         (double)-reports.mRfAndParams.back().mJammerGlo;
5678                 data.jammerInd[GNSS_LOC_SIGNAL_TYPE_GLONASS_G1] =
5679                         (double)reports.mRfAndParams.back().mJammerGlo;
5680             }
5681             if (GNSS_INVALID_JAMMER_IND != reports.mRfAndParams.back().mJammerBds) {
5682                 data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_BEIDOU_B1_I] |=
5683                         GNSS_LOC_DATA_AGC_BIT | GNSS_LOC_DATA_JAMMER_IND_BIT;
5684                 data.agc[GNSS_LOC_SIGNAL_TYPE_BEIDOU_B1_I] =
5685                         (double)-reports.mRfAndParams.back().mJammerBds;
5686                 data.jammerInd[GNSS_LOC_SIGNAL_TYPE_BEIDOU_B1_I] =
5687                         (double)reports.mRfAndParams.back().mJammerBds;
5688             }
5689             if (GNSS_INVALID_JAMMER_IND != reports.mRfAndParams.back().mJammerGal) {
5690                 data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_GALILEO_E1_C] |=
5691                         GNSS_LOC_DATA_AGC_BIT | GNSS_LOC_DATA_JAMMER_IND_BIT;
5692                 data.agc[GNSS_LOC_SIGNAL_TYPE_GALILEO_E1_C] =
5693                         (double)-reports.mRfAndParams.back().mJammerGal;
5694                 data.jammerInd[GNSS_LOC_SIGNAL_TYPE_GALILEO_E1_C] =
5695                         (double)reports.mRfAndParams.back().mJammerGal;
5696             }
5697         }
5698     }
5699 }
5700 
5701 /* Callbacks registered with loc_net_iface library */
agpsOpenResultCb(bool isSuccess,AGpsExtType agpsType,const char * apn,AGpsBearerType bearerType,void * userDataPtr)5702 static void agpsOpenResultCb (bool isSuccess, AGpsExtType agpsType, const char* apn,
5703         AGpsBearerType bearerType, void* userDataPtr) {
5704     LOC_LOGD("%s]: ", __func__);
5705     if (userDataPtr == nullptr) {
5706         LOC_LOGE("%s]: userDataPtr is nullptr.", __func__);
5707         return;
5708     }
5709     if (apn == nullptr) {
5710         LOC_LOGE("%s]: apn is nullptr.", __func__);
5711         return;
5712     }
5713     GnssAdapter* adapter = (GnssAdapter*)userDataPtr;
5714     if (isSuccess) {
5715         adapter->dataConnOpenCommand(agpsType, apn, strlen(apn), bearerType);
5716     } else {
5717         adapter->dataConnFailedCommand(agpsType);
5718     }
5719 }
5720 
agpsCloseResultCb(bool isSuccess,AGpsExtType agpsType,void * userDataPtr)5721 static void agpsCloseResultCb (bool isSuccess, AGpsExtType agpsType, void* userDataPtr) {
5722     LOC_LOGD("%s]: ", __func__);
5723     if (userDataPtr == nullptr) {
5724         LOC_LOGE("%s]: userDataPtr is nullptr.", __func__);
5725         return;
5726     }
5727     GnssAdapter* adapter = (GnssAdapter*)userDataPtr;
5728     if (isSuccess) {
5729         adapter->dataConnClosedCommand(agpsType);
5730     } else {
5731         adapter->dataConnFailedCommand(agpsType);
5732     }
5733 }
5734 
5735 void
saveGnssEnergyConsumedCallback(GnssEnergyConsumedCallback energyConsumedCb)5736 GnssAdapter::saveGnssEnergyConsumedCallback(GnssEnergyConsumedCallback energyConsumedCb) {
5737     mGnssEnergyConsumedCb = energyConsumedCb;
5738 }
5739 
5740 void
getGnssEnergyConsumedCommand(GnssEnergyConsumedCallback energyConsumedCb)5741 GnssAdapter::getGnssEnergyConsumedCommand(GnssEnergyConsumedCallback energyConsumedCb) {
5742     struct MsgGetGnssEnergyConsumed : public LocMsg {
5743         GnssAdapter& mAdapter;
5744         LocApiBase& mApi;
5745         GnssEnergyConsumedCallback mEnergyConsumedCb;
5746         inline MsgGetGnssEnergyConsumed(GnssAdapter& adapter, LocApiBase& api,
5747                                         GnssEnergyConsumedCallback energyConsumedCb) :
5748             LocMsg(),
5749             mAdapter(adapter),
5750             mApi(api),
5751             mEnergyConsumedCb(energyConsumedCb){}
5752         inline virtual void proc() const {
5753             mAdapter.saveGnssEnergyConsumedCallback(mEnergyConsumedCb);
5754             mApi.getGnssEnergyConsumed();
5755         }
5756     };
5757 
5758     sendMsg(new MsgGetGnssEnergyConsumed(*this, *mLocApi, energyConsumedCb));
5759 }
5760 
5761 void
nfwControlCommand(bool enable)5762 GnssAdapter::nfwControlCommand(bool enable) {
5763     struct MsgControlNfwLocationAccess : public LocMsg {
5764         GnssAdapter& mAdapter;
5765         LocApiBase& mApi;
5766         bool mEnable;
5767         inline MsgControlNfwLocationAccess(GnssAdapter& adapter, LocApiBase& api,
5768             bool enable) :
5769             LocMsg(),
5770             mAdapter(adapter),
5771             mApi(api),
5772             mEnable(enable) {}
5773         inline virtual void proc() const {
5774             GnssConfigGpsLock gpsLock;
5775 
5776             gpsLock = ContextBase::mGps_conf.GPS_LOCK;
5777             if (mEnable) {
5778                 gpsLock &= ~GNSS_CONFIG_GPS_LOCK_NI;
5779             } else {
5780                 gpsLock |= GNSS_CONFIG_GPS_LOCK_NI;
5781             }
5782             ContextBase::mGps_conf.GPS_LOCK = gpsLock;
5783             mApi.sendMsg(new LocApiMsg([&mApi = mApi, gpsLock]() {
5784                 mApi.setGpsLockSync((GnssConfigGpsLock)gpsLock);
5785             }));
5786         }
5787     };
5788 
5789     if (mSupportNfwControl) {
5790         sendMsg(new MsgControlNfwLocationAccess(*this, *mLocApi, enable));
5791     } else {
5792         LOC_LOGw("NFW control is not supported, do not use this for NFW");
5793     }
5794 }
5795 
5796 // Set tunc constrained mode, use 0 session id to indicate
5797 // that no callback is needed. Session id 0 is used for calls that
5798 // are not invoked from the integration api, e.g.: initial configuration
5799 // from the configure file
5800 void
setConstrainedTunc(bool enable,float tuncConstraint,uint32_t energyBudget,uint32_t sessionId)5801 GnssAdapter::setConstrainedTunc(bool enable, float tuncConstraint,
5802                                 uint32_t energyBudget, uint32_t sessionId) {
5803 
5804     mLocConfigInfo.tuncConfigInfo.isValid = true;
5805     mLocConfigInfo.tuncConfigInfo.enable = enable;
5806     mLocConfigInfo.tuncConfigInfo.tuncThresholdMs = tuncConstraint;
5807     mLocConfigInfo.tuncConfigInfo.energyBudget = energyBudget;
5808 
5809     LocApiResponse* locApiResponse = nullptr;
5810     if (sessionId != 0) {
5811         locApiResponse =
5812                 new LocApiResponse(*getContext(),
5813                                    [this, sessionId] (LocationError err) {
5814                                     reportResponse(err, sessionId);});
5815         if (!locApiResponse) {
5816             LOC_LOGe("memory alloc failed");
5817         }
5818     }
5819     mLocApi->setConstrainedTuncMode(
5820             enable, tuncConstraint, energyBudget, locApiResponse);
5821 }
5822 
5823 uint32_t
setConstrainedTuncCommand(bool enable,float tuncConstraint,uint32_t energyBudget)5824 GnssAdapter::setConstrainedTuncCommand (bool enable, float tuncConstraint,
5825                                         uint32_t energyBudget) {
5826     // generated session id will be none-zero
5827     uint32_t sessionId = generateSessionId();
5828     LOC_LOGd("session id %u", sessionId);
5829 
5830     struct MsgEnableTUNC : public LocMsg {
5831         GnssAdapter& mAdapter;
5832         uint32_t mSessionId;
5833         bool mEnable;
5834         float mTuncConstraint;
5835         uint32_t mEnergyBudget;
5836 
5837         inline MsgEnableTUNC(GnssAdapter& adapter,
5838                              uint32_t sessionId,
5839                              bool enable,
5840                              float tuncConstraint,
5841                              uint32_t energyBudget) :
5842             LocMsg(),
5843             mAdapter(adapter),
5844             mSessionId(sessionId),
5845             mEnable(enable),
5846             mTuncConstraint(tuncConstraint),
5847             mEnergyBudget(energyBudget) {}
5848         inline virtual void proc() const {
5849             mAdapter.setConstrainedTunc(mEnable, mTuncConstraint,
5850                                         mEnergyBudget, mSessionId);
5851         }
5852     };
5853 
5854     sendMsg(new MsgEnableTUNC(*this, sessionId, enable,
5855                               tuncConstraint, energyBudget));
5856 
5857     return sessionId;
5858 }
5859 
5860 // Set position assisted clock estimator, use 0 session id to indicate
5861 // that no callback is needed. Session id 0 is used for calls that are
5862 // not invoked from the integration api, e.g.: initial configuration
5863 // from the configure file.
5864 void
setPositionAssistedClockEstimator(bool enable,uint32_t sessionId)5865 GnssAdapter::setPositionAssistedClockEstimator(bool enable,
5866                                                uint32_t sessionId) {
5867 
5868     mLocConfigInfo.paceConfigInfo.isValid = true;
5869     mLocConfigInfo.paceConfigInfo.enable = enable;
5870     LocApiResponse* locApiResponse = nullptr;
5871     if (sessionId != 0) {
5872         locApiResponse =
5873                 new LocApiResponse(*getContext(),
5874                                    [this, sessionId] (LocationError err) {
5875                                    reportResponse(err, sessionId);});
5876         if (!locApiResponse) {
5877             LOC_LOGe("memory alloc failed");
5878         }
5879     }
5880     mLocApi->setPositionAssistedClockEstimatorMode(enable, locApiResponse);
5881 }
5882 
5883 uint32_t
setPositionAssistedClockEstimatorCommand(bool enable)5884 GnssAdapter::setPositionAssistedClockEstimatorCommand(bool enable) {
5885     // generated session id will be none-zero
5886     uint32_t sessionId = generateSessionId();
5887     LOC_LOGd("session id %u", sessionId);
5888 
5889     struct MsgEnablePACE : public LocMsg {
5890         GnssAdapter& mAdapter;
5891         uint32_t mSessionId;
5892         bool mEnable;
5893         inline MsgEnablePACE(GnssAdapter& adapter,
5894                              uint32_t sessionId, bool enable) :
5895             LocMsg(),
5896             mAdapter(adapter),
5897             mSessionId(sessionId),
5898             mEnable(enable){}
5899         inline virtual void proc() const {
5900             mAdapter.setPositionAssistedClockEstimator(mEnable, mSessionId);
5901         }
5902     };
5903 
5904     sendMsg(new MsgEnablePACE(*this, sessionId, enable));
5905     return sessionId;
5906 }
5907 
gnssUpdateSvConfig(uint32_t sessionId,const GnssSvTypeConfig & constellationEnablementConfig,const GnssSvIdConfig & blacklistSvConfig)5908 void GnssAdapter::gnssUpdateSvConfig(
5909         uint32_t sessionId, const GnssSvTypeConfig& constellationEnablementConfig,
5910         const GnssSvIdConfig&   blacklistSvConfig) {
5911 
5912     // suspend all tracking sessions to apply the constellation config
5913     suspendSessions();
5914     if (constellationEnablementConfig.size == sizeof(constellationEnablementConfig)) {
5915         // check whether if any constellation is removed from the new config
5916         GnssSvTypesMask currentEnabledMask = mGnssSvTypeConfig.enabledSvTypesMask;
5917         GnssSvTypesMask newEnabledMask = constellationEnablementConfig.enabledSvTypesMask;
5918         GnssSvTypesMask enabledRemoved = currentEnabledMask & (currentEnabledMask ^ newEnabledMask);
5919         // Send reset if any constellation is removed from the enabled list
5920         if (enabledRemoved != 0) {
5921             mLocApi->resetConstellationControl();
5922         }
5923 
5924         // if the constellation config is valid, issue request to modem
5925         // to enable/disable constellation
5926         mLocApi->setConstellationControl(mGnssSvTypeConfig);
5927     } else if (constellationEnablementConfig.size == 0) {
5928         // when the size is not set, meaning reset to modem default
5929         mLocApi->resetConstellationControl();
5930     }
5931     // save the constellation settings to be used for modem SSR
5932     mGnssSvTypeConfig = constellationEnablementConfig;
5933 
5934     // handle blacklisted SV settings
5935     mGnssSvIdConfig   = blacklistSvConfig;
5936     // process blacklist svs info
5937     mBlacklistedSvIds.clear();
5938     // need to save the balcklisted sv info into mBlacklistedSvIds as well
5939     convertFromGnssSvIdConfig(blacklistSvConfig, mBlacklistedSvIds);
5940     LocApiResponse* locApiResponse = new LocApiResponse(*getContext(),
5941             [this, sessionId] (LocationError err) {
5942             reportResponse(err, sessionId);});
5943     if (!locApiResponse) {
5944         LOC_LOGe("memory alloc failed");
5945     }
5946     mLocApi->setBlacklistSv(mGnssSvIdConfig, locApiResponse);
5947 
5948     // resume all tracking sessions after the constellation config has been applied
5949     restartSessions(false);
5950 }
5951 
5952 uint32_t
gnssUpdateSvConfigCommand(const GnssSvTypeConfig & constellationEnablementConfig,const GnssSvIdConfig & blacklistSvConfig)5953 GnssAdapter::gnssUpdateSvConfigCommand(
5954         const GnssSvTypeConfig& constellationEnablementConfig,
5955         const GnssSvIdConfig& blacklistSvConfig) {
5956 
5957     // generated session id will be none-zero
5958     uint32_t sessionId = generateSessionId();
5959     LOC_LOGd("session id %u", sessionId);
5960 
5961     struct MsgUpdateSvConfig : public LocMsg {
5962         GnssAdapter&     mAdapter;
5963         uint32_t         mSessionId;
5964         GnssSvTypeConfig mConstellationEnablementConfig;
5965         GnssSvIdConfig   mBlacklistSvIdConfig;
5966 
5967         inline MsgUpdateSvConfig(GnssAdapter& adapter,
5968                                  uint32_t sessionId,
5969                                  const GnssSvTypeConfig& constellationEnablementConfig,
5970                                  const GnssSvIdConfig& blacklistSvConfig) :
5971             LocMsg(),
5972             mAdapter(adapter),
5973             mSessionId(sessionId),
5974             mConstellationEnablementConfig(constellationEnablementConfig),
5975             mBlacklistSvIdConfig(blacklistSvConfig) {}
5976         inline virtual void proc() const {
5977             mAdapter.gnssUpdateSvConfig(mSessionId, mConstellationEnablementConfig,
5978                                         mBlacklistSvIdConfig);
5979         }
5980     };
5981 
5982     if (sessionId != 0) {
5983         sendMsg(new MsgUpdateSvConfig(*this, sessionId, constellationEnablementConfig,
5984                                       blacklistSvConfig));
5985     }
5986     return sessionId;
5987 }
5988 
gnssUpdateSecondaryBandConfig(uint32_t sessionId,const GnssSvTypeConfig & secondaryBandConfig)5989 void GnssAdapter::gnssUpdateSecondaryBandConfig(
5990         uint32_t sessionId, const GnssSvTypeConfig& secondaryBandConfig) {
5991 
5992     LocApiResponse* locApiResponse = new LocApiResponse(*getContext(),
5993             [this, sessionId] (LocationError err) {
5994             reportResponse(err, sessionId);});
5995     if (!locApiResponse) {
5996         LOC_LOGe("memory alloc failed");
5997     }
5998 
5999     // handle secondary band info
6000     mGnssSeconaryBandConfig = secondaryBandConfig;
6001     gnssSecondaryBandConfigUpdate(locApiResponse);
6002 }
6003 
6004 uint32_t
gnssUpdateSecondaryBandConfigCommand(const GnssSvTypeConfig & secondaryBandConfig)6005 GnssAdapter::gnssUpdateSecondaryBandConfigCommand(
6006         const GnssSvTypeConfig& secondaryBandConfig) {
6007 
6008     // generated session id will be none-zero
6009     uint32_t sessionId = generateSessionId();
6010     LOC_LOGd("session id %u", sessionId);
6011 
6012     struct MsgUpdateSecondaryBandConfig : public LocMsg {
6013         GnssAdapter&     mAdapter;
6014         uint32_t         mSessionId;
6015         GnssSvTypeConfig mSecondaryBandConfig;
6016 
6017         inline MsgUpdateSecondaryBandConfig(GnssAdapter& adapter,
6018                                  uint32_t sessionId,
6019                                  const GnssSvTypeConfig& secondaryBandConfig) :
6020             LocMsg(),
6021             mAdapter(adapter),
6022             mSessionId(sessionId),
6023             mSecondaryBandConfig(secondaryBandConfig) {}
6024         inline virtual void proc() const {
6025             mAdapter.gnssUpdateSecondaryBandConfig(mSessionId,  mSecondaryBandConfig);
6026         }
6027     };
6028 
6029     if (sessionId != 0) {
6030         sendMsg(new MsgUpdateSecondaryBandConfig(*this, sessionId, secondaryBandConfig));
6031     }
6032     return sessionId;
6033 }
6034 
6035 // This function currently retrieves secondary band configuration
6036 // for constellation enablement/disablement.
6037 void
gnssGetSecondaryBandConfig(uint32_t sessionId)6038 GnssAdapter::gnssGetSecondaryBandConfig(uint32_t sessionId) {
6039 
6040     LocApiResponse* locApiResponse = new LocApiResponse(*getContext(),
6041             [this, sessionId] (LocationError err) {
6042             reportResponse(err, sessionId);});
6043     if (!locApiResponse) {
6044         LOC_LOGe("memory alloc failed");
6045     }
6046 
6047     mLocApi->getConstellationMultiBandConfig(sessionId, locApiResponse);
6048 }
6049 
6050 uint32_t
gnssGetSecondaryBandConfigCommand()6051 GnssAdapter::gnssGetSecondaryBandConfigCommand() {
6052 
6053     // generated session id will be none-zero
6054     uint32_t sessionId = generateSessionId();
6055     LOC_LOGd("session id %u", sessionId);
6056 
6057     struct MsgGetSecondaryBandConfig : public LocMsg {
6058         GnssAdapter& mAdapter;
6059         uint32_t     mSessionId;
6060         inline MsgGetSecondaryBandConfig(GnssAdapter& adapter,
6061                               uint32_t sessionId) :
6062             LocMsg(),
6063             mAdapter(adapter),
6064             mSessionId(sessionId) {}
6065         inline virtual void proc() const {
6066             mAdapter.gnssGetSecondaryBandConfig(mSessionId);
6067         }
6068     };
6069 
6070     if (sessionId != 0) {
6071         sendMsg(new MsgGetSecondaryBandConfig(*this, sessionId));
6072     }
6073     return sessionId;
6074 }
6075 
6076 void
configLeverArm(uint32_t sessionId,const LeverArmConfigInfo & configInfo)6077 GnssAdapter::configLeverArm(uint32_t sessionId,
6078                             const LeverArmConfigInfo& configInfo) {
6079 
6080     LocationError err = LOCATION_ERROR_NOT_SUPPORTED;
6081     if (true == mEngHubProxy->configLeverArm(configInfo)) {
6082         err = LOCATION_ERROR_SUCCESS;
6083     }
6084     reportResponse(err, sessionId);
6085 }
6086 
6087 uint32_t
configLeverArmCommand(const LeverArmConfigInfo & configInfo)6088 GnssAdapter::configLeverArmCommand(const LeverArmConfigInfo& configInfo) {
6089 
6090     // generated session id will be none-zero
6091     uint32_t sessionId = generateSessionId();
6092     LOC_LOGd("session id %u", sessionId);
6093 
6094     struct MsgConfigLeverArm : public LocMsg {
6095         GnssAdapter&       mAdapter;
6096         uint32_t           mSessionId;
6097         LeverArmConfigInfo mConfigInfo;
6098 
6099         inline MsgConfigLeverArm(GnssAdapter& adapter,
6100                                  uint32_t sessionId,
6101                                  const LeverArmConfigInfo& configInfo) :
6102             LocMsg(),
6103             mAdapter(adapter),
6104             mSessionId(sessionId),
6105             mConfigInfo(configInfo) {}
6106         inline virtual void proc() const {
6107             // save the lever ARM config info for translating position from GNSS antenna based
6108             // to VRP based
6109             if (mConfigInfo.leverArmValidMask & LEVER_ARM_TYPE_GNSS_TO_VRP_BIT) {
6110                 mAdapter.mLocConfigInfo.leverArmConfigInfo.leverArmValidMask |=
6111                         LEVER_ARM_TYPE_GNSS_TO_VRP_BIT;
6112                 mAdapter.mLocConfigInfo.leverArmConfigInfo.gnssToVRP = mConfigInfo.gnssToVRP;
6113             }
6114             mAdapter.configLeverArm(mSessionId, mConfigInfo);
6115         }
6116     };
6117 
6118     sendMsg(new MsgConfigLeverArm(*this, sessionId, configInfo));
6119     return sessionId;
6120 }
6121 
initMeasCorr(bool bSendCbWhenNotSupported)6122 bool GnssAdapter::initMeasCorr(bool bSendCbWhenNotSupported) {
6123     LOC_LOGv("GnssAdapter::initMeasCorr");
6124     /* Message to initialize Measurement Corrections */
6125     struct MsgInitMeasCorr : public LocMsg {
6126         GnssAdapter& mAdapter;
6127         GnssMeasurementCorrectionsCapabilitiesMask mCapMask;
6128 
6129         inline MsgInitMeasCorr(GnssAdapter& adapter,
6130                 GnssMeasurementCorrectionsCapabilitiesMask capMask) :
6131             LocMsg(), mAdapter(adapter), mCapMask(capMask) {
6132             LOC_LOGv("MsgInitMeasCorr");
6133         }
6134 
6135         inline virtual void proc() const {
6136             LOC_LOGv("MsgInitMeasCorr::proc()");
6137 
6138             mAdapter.mMeasCorrSetCapabilitiesCb(mCapMask);
6139         }
6140     };
6141     if (ContextBase::isFeatureSupported(LOC_SUPPORTED_FEATURE_MEASUREMENTS_CORRECTION)) {
6142         sendMsg(new MsgInitMeasCorr(*this, GNSS_MEAS_CORR_LOS_SATS |
6143                 GNSS_MEAS_CORR_EXCESS_PATH_LENGTH | GNSS_MEAS_CORR_REFLECTING_PLANE));
6144         return true;
6145     } else {
6146         LOC_LOGv("MEASUREMENTS_CORRECTION feature is not supported in the modem");
6147         if (bSendCbWhenNotSupported) {
6148             sendMsg(new MsgInitMeasCorr(*this, 0));
6149         }
6150         return false;
6151     }
6152 }
6153 
openMeasCorrCommand(const measCorrSetCapabilitiesCb setCapabilitiesCb)6154 bool GnssAdapter::openMeasCorrCommand(const measCorrSetCapabilitiesCb setCapabilitiesCb) {
6155     LOC_LOGi("GnssAdapter::openMeasCorrCommand");
6156 
6157     /* Send message to initialize Measurement Corrections */
6158         mMeasCorrSetCapabilitiesCb = setCapabilitiesCb;
6159         mIsMeasCorrInterfaceOpen = true;
6160         if (isEngineCapabilitiesKnown()) {
6161         LOC_LOGv("Capabilities are known, proceed with measurement corrections init");
6162             return initMeasCorr(false);
6163         } else {
6164         LOC_LOGv("Capabilities are not known, wait for open");
6165             return true;
6166         }
6167 }
6168 
measCorrSetCorrectionsCommand(const GnssMeasurementCorrections gnssMeasCorr)6169 bool GnssAdapter::measCorrSetCorrectionsCommand(const GnssMeasurementCorrections gnssMeasCorr) {
6170     LOC_LOGi("GnssAdapter::measCorrSetCorrectionsCommand");
6171 
6172     /* Message to set Measurement Corrections */
6173     struct MsgSetCorrectionsMeasCorr : public LocMsg {
6174         const GnssMeasurementCorrections mGnssMeasCorr;
6175         GnssAdapter& mAdapter;
6176         LocApiBase& mApi;
6177 
6178         inline MsgSetCorrectionsMeasCorr(
6179             const GnssMeasurementCorrections gnssMeasCorr,
6180             GnssAdapter& adapter,
6181             LocApiBase& api) :
6182             LocMsg(),
6183             mGnssMeasCorr(gnssMeasCorr),
6184             mAdapter(adapter),
6185             mApi(api) {
6186             LOC_LOGv("MsgSetCorrectionsMeasCorr");
6187         }
6188 
6189         inline virtual void proc() const {
6190             LOC_LOGv("MsgSetCorrectionsMeasCorr::proc()");
6191             mApi.setMeasurementCorrections(mGnssMeasCorr);
6192         }
6193     };
6194 
6195     if (ContextBase::isFeatureSupported(LOC_SUPPORTED_FEATURE_MEASUREMENTS_CORRECTION)) {
6196         sendMsg(new MsgSetCorrectionsMeasCorr(gnssMeasCorr, *this, *mLocApi));
6197         return true;
6198     } else {
6199         LOC_LOGw("Measurement Corrections are not supported!");
6200         return false;
6201     }
6202 }
antennaInfoInitCommand(const antennaInfoCb antennaInfoCallback)6203 uint32_t GnssAdapter::antennaInfoInitCommand(const antennaInfoCb antennaInfoCallback) {
6204     LOC_LOGi("GnssAdapter::antennaInfoInitCommand");
6205 
6206     /* Message to initialize Antenna Information */
6207     struct MsgInitAi : public LocMsg {
6208         const antennaInfoCb mAntennaInfoCb;
6209         GnssAdapter& mAdapter;
6210 
6211         inline MsgInitAi(const antennaInfoCb antennaInfoCallback, GnssAdapter& adapter) :
6212             LocMsg(), mAntennaInfoCb(antennaInfoCallback), mAdapter(adapter) {
6213             LOC_LOGv("MsgInitAi");
6214         }
6215 
6216         inline virtual void proc() const {
6217             LOC_LOGv("MsgInitAi::proc()");
6218             mAdapter.reportGnssAntennaInformation(mAntennaInfoCb);
6219         }
6220     };
6221     if (mIsAntennaInfoInterfaceOpened) {
6222         return ANTENNA_INFO_ERROR_ALREADY_INIT;
6223     } else {
6224         mIsAntennaInfoInterfaceOpened = true;
6225         sendMsg(new MsgInitAi(antennaInfoCallback, *this));
6226         return ANTENNA_INFO_SUCCESS;
6227     }
6228 }
6229 
6230 void
configRobustLocation(uint32_t sessionId,bool enable,bool enableForE911)6231 GnssAdapter::configRobustLocation(uint32_t sessionId,
6232                                   bool enable, bool enableForE911) {
6233 
6234     mLocConfigInfo.robustLocationConfigInfo.isValid = true;
6235     mLocConfigInfo.robustLocationConfigInfo.enable = enable;
6236     mLocConfigInfo.robustLocationConfigInfo.enableFor911 = enableForE911;
6237 
6238     LocApiResponse* locApiResponse = nullptr;
6239     if (sessionId != 0) {
6240         locApiResponse =
6241                 new LocApiResponse(*getContext(),
6242                                    [this, sessionId] (LocationError err) {
6243                                    reportResponse(err, sessionId);});
6244         if (!locApiResponse) {
6245             LOC_LOGe("memory alloc failed");
6246         }
6247     }
6248     mLocApi->configRobustLocation(enable, enableForE911, locApiResponse);
6249 }
6250 
configRobustLocationCommand(bool enable,bool enableForE911)6251 uint32_t GnssAdapter::configRobustLocationCommand(
6252         bool enable, bool enableForE911) {
6253 
6254     // generated session id will be none-zero
6255     uint32_t sessionId = generateSessionId();
6256     LOC_LOGd("session id %u", sessionId);
6257 
6258     struct MsgConfigRobustLocation : public LocMsg {
6259         GnssAdapter&     mAdapter;
6260         uint32_t         mSessionId;
6261         bool             mEnable;
6262         bool             mEnableForE911;
6263 
6264         inline MsgConfigRobustLocation(GnssAdapter& adapter,
6265                                 uint32_t sessionId,
6266                                 bool     enable,
6267                                 bool     enableForE911) :
6268             LocMsg(),
6269             mAdapter(adapter),
6270             mSessionId(sessionId),
6271             mEnable(enable),
6272             mEnableForE911(enableForE911) {}
6273         inline virtual void proc() const {
6274             mAdapter.configRobustLocation(mSessionId, mEnable, mEnableForE911);
6275         }
6276     };
6277 
6278     sendMsg(new MsgConfigRobustLocation(*this, sessionId, enable, enableForE911));
6279     return sessionId;
6280 }
6281 
6282 void
configMinGpsWeek(uint32_t sessionId,uint16_t minGpsWeek)6283 GnssAdapter::configMinGpsWeek(uint32_t sessionId, uint16_t minGpsWeek) {
6284     // suspend all sessions for modem to take the min GPS week config
6285     suspendSessions();
6286 
6287     LocApiResponse* locApiResponse = nullptr;
6288     if (sessionId != 0) {
6289         locApiResponse =
6290                 new LocApiResponse(*getContext(),
6291                                    [this, sessionId] (LocationError err) {
6292                                    reportResponse(err, sessionId);});
6293         if (!locApiResponse) {
6294             LOC_LOGe("memory alloc failed");
6295         }
6296     }
6297     mLocApi->configMinGpsWeek(minGpsWeek, locApiResponse);
6298 
6299     // resume all tracking sessions after the min GPS week config
6300     // has been changed
6301     restartSessions(false);
6302 }
6303 
configMinGpsWeekCommand(uint16_t minGpsWeek)6304 uint32_t GnssAdapter::configMinGpsWeekCommand(uint16_t minGpsWeek) {
6305     // generated session id will be none-zero
6306     uint32_t sessionId = generateSessionId();
6307     LOC_LOGd("session id %u", sessionId);
6308 
6309     struct MsgConfigMinGpsWeek : public LocMsg {
6310         GnssAdapter&     mAdapter;
6311         uint32_t         mSessionId;
6312         uint16_t         mMinGpsWeek;
6313 
6314         inline MsgConfigMinGpsWeek(GnssAdapter& adapter,
6315                                    uint32_t sessionId,
6316                                    uint16_t minGpsWeek) :
6317             LocMsg(),
6318             mAdapter(adapter),
6319             mSessionId(sessionId),
6320             mMinGpsWeek(minGpsWeek) {}
6321         inline virtual void proc() const {
6322             mAdapter.configMinGpsWeek(mSessionId, mMinGpsWeek);
6323         }
6324     };
6325 
6326     sendMsg(new MsgConfigMinGpsWeek(*this, sessionId, minGpsWeek));
6327     return sessionId;
6328 }
6329 
configDeadReckoningEngineParamsCommand(const DeadReckoningEngineConfig & dreConfig)6330 uint32_t GnssAdapter::configDeadReckoningEngineParamsCommand(
6331         const DeadReckoningEngineConfig& dreConfig) {
6332 
6333     // generated session id will be none-zero
6334     uint32_t sessionId = generateSessionId();
6335     LOC_LOGd("session id %u", sessionId);
6336 
6337     struct MsgConfigDrEngine : public LocMsg {
6338         GnssAdapter& mAdapter;
6339         uint32_t     mSessionId;
6340         DeadReckoningEngineConfig mDreConfig;
6341 
6342         inline MsgConfigDrEngine(GnssAdapter& adapter,
6343                                   uint32_t sessionId,
6344                                   const DeadReckoningEngineConfig& dreConfig) :
6345             LocMsg(),
6346             mAdapter(adapter),
6347             mSessionId(sessionId),
6348             mDreConfig(dreConfig) {}
6349         inline virtual void proc() const {
6350             LocationError err = LOCATION_ERROR_NOT_SUPPORTED;
6351             if (true == mAdapter.mEngHubProxy->configDeadReckoningEngineParams(mDreConfig)) {
6352                 err = LOCATION_ERROR_SUCCESS;
6353             }
6354             mAdapter.reportResponse(err, mSessionId);
6355         }
6356     };
6357 
6358     sendMsg(new MsgConfigDrEngine(*this, sessionId, dreConfig));
6359     return sessionId;
6360 }
6361 
configEngineRunStateCommand(PositioningEngineMask engType,LocEngineRunState engState)6362 uint32_t GnssAdapter::configEngineRunStateCommand(
6363         PositioningEngineMask engType, LocEngineRunState engState) {
6364 
6365     // generated session id will be none-zero
6366     uint32_t sessionId = generateSessionId();
6367     LOC_LOGe("session id %u, eng type 0x%x, eng state %d, dre enabled %d",
6368              sessionId, engType, engState, mDreIntEnabled);
6369 
6370     struct MsgConfigEngineRunState : public LocMsg {
6371         GnssAdapter& mAdapter;
6372         uint32_t     mSessionId;
6373         PositioningEngineMask mEngType;
6374         LocEngineRunState mEngState;
6375 
6376         inline MsgConfigEngineRunState(GnssAdapter& adapter,
6377                                        uint32_t sessionId,
6378                                        PositioningEngineMask engType,
6379                                        LocEngineRunState engState) :
6380             LocMsg(),
6381             mAdapter(adapter),
6382             mSessionId(sessionId),
6383             mEngType(engType),
6384             mEngState(engState) {}
6385         inline virtual void proc() const {
6386             LocationError err = LOCATION_ERROR_NOT_SUPPORTED;
6387             // Currently, only DR engine supports pause/resume request
6388             if ((mEngType == DEAD_RECKONING_ENGINE) &&
6389                 (mAdapter.mDreIntEnabled == true)) {
6390                 if (true == mAdapter.mEngHubProxy->configEngineRunState(mEngType, mEngState)) {
6391                     err = LOCATION_ERROR_SUCCESS;
6392                 }
6393             }
6394             mAdapter.reportResponse(err, mSessionId);
6395         }
6396     };
6397 
6398     sendMsg(new MsgConfigEngineRunState(*this, sessionId, engType, engState));
6399 
6400     return sessionId;
6401 }
6402 
reportGnssConfigEvent(uint32_t sessionId,const GnssConfig & gnssConfig)6403 void GnssAdapter::reportGnssConfigEvent(uint32_t sessionId, const GnssConfig& gnssConfig)
6404 {
6405     struct MsgReportGnssConfig : public LocMsg {
6406         GnssAdapter& mAdapter;
6407         uint32_t     mSessionId;
6408         mutable GnssConfig   mGnssConfig;
6409         inline MsgReportGnssConfig(GnssAdapter& adapter,
6410                                    uint32_t sessionId,
6411                                    const GnssConfig& gnssConfig) :
6412             LocMsg(),
6413             mAdapter(adapter),
6414             mSessionId(sessionId),
6415             mGnssConfig(gnssConfig) {}
6416         inline virtual void proc() const {
6417             // Invoke control clients config callback
6418             if (nullptr != mAdapter.mControlCallbacks.gnssConfigCb) {
6419                 mAdapter.mControlCallbacks.gnssConfigCb(mSessionId, mGnssConfig);
6420             } else {
6421                 LOC_LOGe("Failed to report, callback not registered");
6422             }
6423         }
6424     };
6425 
6426     sendMsg(new MsgReportGnssConfig(*this, sessionId, gnssConfig));
6427 }
6428 
6429 /* ==== Eng Hub Proxy ================================================================= */
6430 /* ======== UTILITIES ================================================================= */
6431 void
initEngHubProxyCommand()6432 GnssAdapter::initEngHubProxyCommand() {
6433     LOC_LOGD("%s]: ", __func__);
6434 
6435     struct MsgInitEngHubProxy : public LocMsg {
6436         GnssAdapter* mAdapter;
6437         inline MsgInitEngHubProxy(GnssAdapter* adapter) :
6438             LocMsg(),
6439             mAdapter(adapter) {}
6440         inline virtual void proc() const {
6441             mAdapter->initEngHubProxy();
6442         }
6443     };
6444 
6445     sendMsg(new MsgInitEngHubProxy(this));
6446 }
6447 
6448 bool
initEngHubProxy()6449 GnssAdapter::initEngHubProxy() {
6450     static bool firstTime = true;
6451     static bool engHubLoadSuccessful = false;
6452 
6453     const char *error = nullptr;
6454     unsigned int processListLength = 0;
6455     loc_process_info_s_type* processInfoList = nullptr;
6456 
6457     do {
6458         // load eng hub only once
6459         if (firstTime == false) {
6460             break;
6461         }
6462 
6463         int rc = loc_read_process_conf(LOC_PATH_IZAT_CONF, &processListLength,
6464                                        &processInfoList);
6465         if (rc != 0) {
6466             LOC_LOGE("%s]: failed to parse conf file", __func__);
6467             break;
6468         }
6469 
6470         bool pluginDaemonEnabled = false;
6471         // go over the conf table to see whether any plugin daemon is enabled
6472         for (unsigned int i = 0; i < processListLength; i++) {
6473             if ((strncmp(processInfoList[i].name[0], PROCESS_NAME_ENGINE_SERVICE,
6474                          strlen(PROCESS_NAME_ENGINE_SERVICE)) == 0) &&
6475                 (processInfoList[i].proc_status == ENABLED)) {
6476                 pluginDaemonEnabled = true;
6477                 // check if this is DRE-INT engine
6478                 if ((processInfoList[i].args[1]!= nullptr) &&
6479                     (strncmp(processInfoList[i].args[1], "DRE-INT", sizeof("DRE-INT")) == 0)) {
6480                     mDreIntEnabled = true;
6481                     break;
6482                 }
6483             }
6484         }
6485 
6486         // no plugin daemon is enabled for this platform,
6487         // check if external engine is present for which we need
6488         // libloc_eng_hub.so to be loaded
6489         if (pluginDaemonEnabled == false) {
6490             UTIL_READ_CONF(LOC_PATH_IZAT_CONF, izatConfParamTable);
6491             if (!loadEngHubForExternalEngine) {
6492                 break;
6493             }
6494         }
6495 
6496         // load the engine hub .so, if the .so is not present
6497         // all EngHubProxyBase calls will turn into no-op.
6498         void *handle = nullptr;
6499         if ((handle = dlopen("libloc_eng_hub.so", RTLD_NOW)) == nullptr) {
6500             if ((error = dlerror()) != nullptr) {
6501                 LOC_LOGE("%s]: libloc_eng_hub.so not found %s !", __func__, error);
6502             }
6503             break;
6504         }
6505 
6506         // prepare the callback functions
6507         // callback function for engine hub to report back position event
6508         GnssAdapterReportEnginePositionsEventCb reportPositionEventCb =
6509             [this](int count, EngineLocationInfo* locationArr) {
6510                     // report from engine hub on behalf of PPE will be treated as fromUlp
6511                     reportEnginePositionsEvent(count, locationArr);
6512             };
6513 
6514         // callback function for engine hub to report back sv event
6515         GnssAdapterReportSvEventCb reportSvEventCb =
6516             [this](const GnssSvNotification& svNotify, bool fromEngineHub) {
6517                    reportSvEvent(svNotify, fromEngineHub);
6518             };
6519 
6520         // callback function for engine hub to request for complete aiding data
6521         GnssAdapterReqAidingDataCb reqAidingDataCb =
6522             [this] (const GnssAidingDataSvMask& svDataMask) {
6523             mLocApi->requestForAidingData(svDataMask);
6524         };
6525 
6526         GnssAdapterUpdateNHzRequirementCb updateNHzRequirementCb =
6527             [this] (bool nHzNeeded, bool nHzMeasNeeded) {
6528 
6529             if (nHzMeasNeeded &&
6530                     (!checkMask(LOC_API_ADAPTER_BIT_GNSS_NHZ_MEASUREMENT))) {
6531                 updateEvtMask(LOC_API_ADAPTER_BIT_GNSS_NHZ_MEASUREMENT,
6532                     LOC_REGISTRATION_MASK_ENABLED);
6533             } else if (checkMask(LOC_API_ADAPTER_BIT_GNSS_NHZ_MEASUREMENT)) {
6534                 updateEvtMask(LOC_API_ADAPTER_BIT_GNSS_NHZ_MEASUREMENT,
6535                     LOC_REGISTRATION_MASK_DISABLED);
6536             }
6537 
6538             if (mNHzNeeded != nHzNeeded) {
6539                 mNHzNeeded = nHzNeeded;
6540                 checkAndRestartSPESession();
6541             }
6542         };
6543 
6544         GnssAdapterUpdateQwesFeatureStatusCb updateQwesFeatureStatusCb =
6545             [this] (const std::unordered_map<LocationQwesFeatureType, bool> &featureMap) {
6546             reportQwesCapabilities(featureMap);
6547         };
6548 
6549         getEngHubProxyFn* getter = (getEngHubProxyFn*) dlsym(handle, "getEngHubProxy");
6550         if(getter != nullptr) {
6551             EngineHubProxyBase* hubProxy = (*getter) (mMsgTask, mSystemStatus->getOsObserver(),
6552                       reportPositionEventCb,
6553                       reportSvEventCb, reqAidingDataCb,
6554                       updateNHzRequirementCb,
6555                       updateQwesFeatureStatusCb);
6556             if (hubProxy != nullptr) {
6557                 mEngHubProxy = hubProxy;
6558                 engHubLoadSuccessful = true;
6559             }
6560         }
6561         else {
6562             LOC_LOGD("%s]: entered, did not find function", __func__);
6563         }
6564 
6565         LOC_LOGD("%s]: first time initialization %d, returned %d",
6566                  __func__, firstTime, engHubLoadSuccessful);
6567 
6568     } while (0);
6569 
6570     if (processInfoList != nullptr) {
6571         free (processInfoList);
6572         processInfoList = nullptr;
6573     }
6574 
6575     firstTime = false;
6576     return engHubLoadSuccessful;
6577 }
6578 
6579 std::vector<double>
parseDoublesString(char * dString)6580 GnssAdapter::parseDoublesString(char* dString) {
6581     std::vector<double> dVector;
6582     char* tmp = NULL;
6583     char* substr;
6584 
6585     dVector.clear();
6586     for (substr = strtok_r(dString, " ", &tmp);
6587         substr != NULL;
6588         substr = strtok_r(NULL, " ", &tmp)) {
6589         dVector.push_back(std::stod(substr));
6590     }
6591     return dVector;
6592 }
6593 
6594 void
reportGnssAntennaInformation(const antennaInfoCb antennaInfoCallback)6595 GnssAdapter::reportGnssAntennaInformation(const antennaInfoCb antennaInfoCallback)
6596 {
6597 #define MAX_TEXT_WIDTH      50
6598 #define MAX_COLUMN_WIDTH    20
6599 
6600     /* parse antenna_corrections file and fill in
6601     a vector of GnssAntennaInformation data structure */
6602 
6603     std::vector<GnssAntennaInformation> gnssAntennaInformations;
6604     GnssAntennaInformation gnssAntennaInfo;
6605 
6606     uint32_t antennaInfoVectorSize;
6607     loc_param_s_type ant_info_vector_table[] =
6608     {
6609         { "ANTENNA_INFO_VECTOR_SIZE", &antennaInfoVectorSize, NULL, 'n' }
6610     };
6611     UTIL_READ_CONF(LOC_PATH_ANT_CORR, ant_info_vector_table);
6612 
6613     for (uint32_t i = 0; i < antennaInfoVectorSize; i++) {
6614         double carrierFrequencyMHz;
6615         char pcOffsetStr[LOC_MAX_PARAM_STRING];
6616         uint32_t numberOfRows = 0;
6617         uint32_t numberOfColumns = 0;
6618         uint32_t numberOfRowsSGC = 0;
6619         uint32_t numberOfColumnsSGC = 0;
6620 
6621         gnssAntennaInfo.phaseCenterVariationCorrectionMillimeters.clear();
6622         gnssAntennaInfo.phaseCenterVariationCorrectionUncertaintyMillimeters.clear();
6623         gnssAntennaInfo.signalGainCorrectionDbi.clear();
6624         gnssAntennaInfo.signalGainCorrectionUncertaintyDbi.clear();
6625         string s1 = "CARRIER_FREQUENCY_";
6626         s1 += to_string(i);
6627         string s2 = "PC_OFFSET_";
6628         s2 += to_string(i);
6629         string s3 = "NUMBER_OF_ROWS_";
6630         s3 += to_string(i);
6631         string s4 = "NUMBER_OF_COLUMNS_";
6632         s4 += to_string(i);
6633         string s5 = "NUMBER_OF_ROWS_SGC_";
6634         s5 += to_string(i);
6635         string s6 = "NUMBER_OF_COLUMNS_SGC_";
6636         s6 += to_string(i);
6637 
6638         gnssAntennaInfo.size = sizeof(gnssAntennaInfo);
6639         loc_param_s_type ant_cf_table[] =
6640         {
6641             { s1.c_str(), &carrierFrequencyMHz, NULL, 'f' },
6642             { s2.c_str(), &pcOffsetStr, NULL, 's' },
6643             { s3.c_str(), &numberOfRows, NULL, 'n' },
6644             { s4.c_str(), &numberOfColumns, NULL, 'n' },
6645             { s5.c_str(), &numberOfRowsSGC, NULL, 'n' },
6646             { s6.c_str(), &numberOfColumnsSGC, NULL, 'n' },
6647         };
6648         UTIL_READ_CONF(LOC_PATH_ANT_CORR, ant_cf_table);
6649 
6650         if (0 == numberOfRowsSGC) {
6651             numberOfRowsSGC = numberOfRows;
6652         }
6653         if (0 == numberOfColumnsSGC) {
6654             numberOfColumnsSGC = numberOfColumns;
6655         }
6656 
6657         gnssAntennaInfo.carrierFrequencyMHz = carrierFrequencyMHz;
6658 
6659         // now parse pcOffsetStr to get each entry
6660         std::vector<double> pcOffset;
6661         pcOffset = parseDoublesString(pcOffsetStr);
6662         gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters.size =
6663                 sizeof(gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters);
6664         gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters.x = pcOffset[0];
6665         gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters.xUncertainty = pcOffset[1];
6666         gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters.y = pcOffset[2];
6667         gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters.yUncertainty = pcOffset[3];
6668         gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters.z = pcOffset[4];
6669         gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters.zUncertainty = pcOffset[5];
6670 
6671         uint16_t array_size = MAX_TEXT_WIDTH + MAX_COLUMN_WIDTH*numberOfColumns;
6672         uint16_t array_size_SGC = MAX_TEXT_WIDTH + MAX_COLUMN_WIDTH*numberOfColumnsSGC;
6673         for (uint32_t j = 0; j < numberOfRows; j++) {
6674             char pcVarCorrStr[array_size];
6675             char pcVarCorrUncStr[array_size];
6676 
6677             string s1 = "PC_VARIATION_CORRECTION_" + to_string(i) + "_ROW_";
6678             s1 += to_string(j);
6679             string s2 = "PC_VARIATION_CORRECTION_UNC_" + to_string(i) + "_ROW_";
6680             s2 += to_string(j);
6681 
6682             loc_param_s_type ant_row_table[] =
6683             {
6684                 { s1.c_str(), &pcVarCorrStr, NULL, 's' },
6685                 { s2.c_str(), &pcVarCorrUncStr, NULL, 's' },
6686             };
6687             UTIL_READ_CONF_LONG(LOC_PATH_ANT_CORR, ant_row_table, array_size);
6688 
6689             gnssAntennaInfo.phaseCenterVariationCorrectionMillimeters.push_back(
6690                     parseDoublesString(pcVarCorrStr));
6691             gnssAntennaInfo.phaseCenterVariationCorrectionUncertaintyMillimeters.push_back(
6692                     parseDoublesString(pcVarCorrUncStr));
6693         }
6694         for (uint32_t j = 0; j < numberOfRowsSGC; j++) {
6695             char sigGainCorrStr[array_size_SGC];
6696             char sigGainCorrUncStr[array_size_SGC];
6697 
6698             string s3 = "SIGNAL_GAIN_CORRECTION_" + to_string(i) + "_ROW_";
6699             s3 += to_string(j);
6700             string s4 = "SIGNAL_GAIN_CORRECTION_UNC_" + to_string(i) + "_ROW_";
6701             s4 += to_string(j);
6702 
6703             loc_param_s_type ant_row_table[] =
6704             {
6705                 { s3.c_str(), &sigGainCorrStr, NULL, 's' },
6706                 { s4.c_str(), &sigGainCorrUncStr, NULL, 's' },
6707             };
6708             UTIL_READ_CONF_LONG(LOC_PATH_ANT_CORR, ant_row_table, array_size_SGC);
6709 
6710             gnssAntennaInfo.signalGainCorrectionDbi.push_back(
6711                     parseDoublesString(sigGainCorrStr));
6712             gnssAntennaInfo.signalGainCorrectionUncertaintyDbi.push_back(
6713                     parseDoublesString(sigGainCorrUncStr));
6714         }
6715         gnssAntennaInformations.push_back(std::move(gnssAntennaInfo));
6716     }
6717     if (antennaInfoVectorSize > 0)
6718         antennaInfoCallback(gnssAntennaInformations);
6719 }
6720 
6721 /* ==== DGnss Usable Reporter ========================================================= */
6722 /* ======== UTILITIES ================================================================= */
6723 
initCDFWService()6724 void GnssAdapter::initCDFWService()
6725 {
6726     LOC_LOGv("mCdfwInterface %p", mCdfwInterface);
6727     if (nullptr == mCdfwInterface) {
6728         void* libHandle = nullptr;
6729         const char* libName = "libcdfw.so";
6730 
6731         libHandle = nullptr;
6732         getCdfwInterface getter  = (getCdfwInterface)dlGetSymFromLib(libHandle,
6733                           libName, "getQCdfwInterface");
6734         if (nullptr == getter) {
6735             LOC_LOGe("dlGetSymFromLib getQCdfwInterface failed");
6736         } else {
6737             mCdfwInterface = getter();
6738         }
6739 
6740         if (nullptr != mCdfwInterface) {
6741             QDgnssSessionActiveCb qDgnssSessionActiveCb = [this] (bool sessionActive) {
6742                 mDGnssNeedReport = sessionActive;
6743             };
6744             mCdfwInterface->startDgnssApiService(*mMsgTask);
6745             mQDgnssListenerHDL = mCdfwInterface->createUsableReporter(qDgnssSessionActiveCb);
6746         }
6747     }
6748 }
6749 
6750 /*==== DGnss Ntrip Source ==========================================================*/
enablePPENtripStreamCommand(const GnssNtripConnectionParams & params,bool enableRTKEngine)6751 void GnssAdapter::enablePPENtripStreamCommand(const GnssNtripConnectionParams& params,
6752                                               bool enableRTKEngine) {
6753 
6754     (void)enableRTKEngine; //future parameter, not used
6755 
6756     struct enableNtripMsg : public LocMsg {
6757         GnssAdapter& mAdapter;
6758         const GnssNtripConnectionParams& mParams;
6759 
6760         inline enableNtripMsg(GnssAdapter& adapter,
6761                 const GnssNtripConnectionParams& params) :
6762             LocMsg(),
6763             mAdapter(adapter),
6764             mParams(std::move(params)) {}
6765         inline virtual void proc() const {
6766             mAdapter.handleEnablePPENtrip(mParams);
6767         }
6768     };
6769     sendMsg(new enableNtripMsg(*this, params));
6770 }
6771 
handleEnablePPENtrip(const GnssNtripConnectionParams & params)6772 void GnssAdapter::handleEnablePPENtrip(const GnssNtripConnectionParams& params) {
6773     LOC_LOGd("%d %s %d %s %s %s %d mSendNmeaConsent %d",
6774              params.useSSL, params.hostNameOrIp.data(), params.port,
6775              params.mountPoint.data(), params.username.data(), params.password.data(),
6776              params.requiresNmeaLocation, mSendNmeaConsent);
6777 
6778     GnssNtripConnectionParams* pNtripParams = &(mStartDgnssNtripParams.ntripParams);
6779 
6780     if (pNtripParams->useSSL == params.useSSL &&
6781             0 == pNtripParams->hostNameOrIp.compare(params.hostNameOrIp) &&
6782             pNtripParams->port == params.port &&
6783             0 == pNtripParams->mountPoint.compare(params.mountPoint) &&
6784             0 == pNtripParams->username.compare(params.username) &&
6785             0 == pNtripParams->password.compare(params.password) &&
6786             pNtripParams->requiresNmeaLocation == params.requiresNmeaLocation &&
6787             mDgnssState & DGNSS_STATE_ENABLE_NTRIP_COMMAND) {
6788         LOC_LOGd("received same Ntrip param");
6789         return;
6790     }
6791 
6792     mDgnssState |= DGNSS_STATE_ENABLE_NTRIP_COMMAND;
6793     mDgnssState |= DGNSS_STATE_NO_NMEA_PENDING;
6794     mDgnssState &= ~DGNSS_STATE_NTRIP_SESSION_STARTED;
6795 
6796     mStartDgnssNtripParams.ntripParams = std::move(params);
6797     mStartDgnssNtripParams.nmea.clear();
6798     if (mSendNmeaConsent && pNtripParams->requiresNmeaLocation) {
6799         mDgnssState &= ~DGNSS_STATE_NO_NMEA_PENDING;
6800         mDgnssLastNmeaBootTimeMilli = 0;
6801         return;
6802     }
6803 
6804     checkUpdateDgnssNtrip(false);
6805 }
6806 
disablePPENtripStreamCommand()6807 void GnssAdapter::disablePPENtripStreamCommand() {
6808     struct disableNtripMsg : public LocMsg {
6809         GnssAdapter& mAdapter;
6810 
6811         inline disableNtripMsg(GnssAdapter& adapter) :
6812             LocMsg(),
6813             mAdapter(adapter) {}
6814         inline virtual void proc() const {
6815             mAdapter.handleDisablePPENtrip();
6816         }
6817     };
6818     sendMsg(new disableNtripMsg(*this));
6819 }
6820 
handleDisablePPENtrip()6821 void GnssAdapter::handleDisablePPENtrip() {
6822     mDgnssState &= ~DGNSS_STATE_ENABLE_NTRIP_COMMAND;
6823     mDgnssState |= DGNSS_STATE_NO_NMEA_PENDING;
6824     stopDgnssNtrip();
6825 }
6826 
checkUpdateDgnssNtrip(bool isLocationValid)6827 void GnssAdapter::checkUpdateDgnssNtrip(bool isLocationValid) {
6828     LOC_LOGd("isInSession %d mDgnssState 0x%x isLocationValid %d",
6829             isInSession(), mDgnssState, isLocationValid);
6830     if (isInSession()) {
6831         uint64_t curBootTime = getBootTimeMilliSec();
6832         if (mDgnssState == (DGNSS_STATE_ENABLE_NTRIP_COMMAND | DGNSS_STATE_NO_NMEA_PENDING)) {
6833             mDgnssState |= DGNSS_STATE_NTRIP_SESSION_STARTED;
6834             mXtraObserver.startDgnssSource(mStartDgnssNtripParams);
6835             if (isDgnssNmeaRequired()) {
6836                 mDgnssLastNmeaBootTimeMilli = curBootTime;
6837             }
6838         } else if ((mDgnssState & DGNSS_STATE_NTRIP_SESSION_STARTED) && isLocationValid &&
6839             isDgnssNmeaRequired() &&
6840             curBootTime - mDgnssLastNmeaBootTimeMilli > DGNSS_RANGE_UPDATE_TIME_10MIN_IN_MILLI ) {
6841             mXtraObserver.updateNmeaToDgnssServer(mStartDgnssNtripParams.nmea);
6842             mDgnssLastNmeaBootTimeMilli = curBootTime;
6843         }
6844     }
6845 }
6846 
stopDgnssNtrip()6847 void GnssAdapter::stopDgnssNtrip() {
6848     LOC_LOGd("isInSession %d mDgnssState 0x%x", isInSession(), mDgnssState);
6849     mStartDgnssNtripParams.nmea.clear();
6850     if (mDgnssState & DGNSS_STATE_NTRIP_SESSION_STARTED) {
6851         mDgnssState &= ~DGNSS_STATE_NTRIP_SESSION_STARTED;
6852         mXtraObserver.stopDgnssSource();
6853     }
6854 }
6855 
reportGGAToNtrip(const char * nmea)6856 void GnssAdapter::reportGGAToNtrip(const char* nmea) {
6857 
6858 #define POS_OF_GGA (3)  //start position of "GGA"
6859 #define COMMAS_BEFORE_VALID (6) //"$GPGGA,,,,,,0,,,,,,,,*hh"
6860 
6861     if (!isDgnssNmeaRequired()) {
6862         return;
6863     }
6864 
6865     if (nullptr == nmea || 0 == strlen(nmea)) {
6866         return;
6867     }
6868 
6869     string nmeaString(nmea);
6870     size_t foundPos = nmeaString.find("GGA");
6871     size_t foundNth = 0;
6872     string GGAString;
6873 
6874     if (foundPos != string::npos && foundPos >= POS_OF_GGA) {
6875         size_t foundNextSentence = nmeaString.find("$", foundPos);
6876         if (foundNextSentence != string::npos) {
6877             /* remove other sentences after GGA */
6878             GGAString = nmeaString.substr(foundPos - POS_OF_GGA, foundNextSentence);
6879         } else {
6880             /* GGA is the last sentence */
6881             GGAString = nmeaString.substr(foundPos - POS_OF_GGA);
6882         }
6883         LOC_LOGd("GGAString %s", GGAString.c_str());
6884 
6885         foundPos = GGAString.find(",");
6886         while (foundPos != string::npos && foundNth < COMMAS_BEFORE_VALID) {
6887             foundPos++;
6888             foundNth++;
6889             foundPos = GGAString.find(",", foundPos);
6890         }
6891 
6892         if (COMMAS_BEFORE_VALID == foundNth && GGAString.at(foundPos-1) != '0') {
6893             mDgnssState |= DGNSS_STATE_NO_NMEA_PENDING;
6894             mStartDgnssNtripParams.nmea = std::move(GGAString);
6895             checkUpdateDgnssNtrip(true);
6896         }
6897     }
6898 
6899     return;
6900 }
6901