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