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