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