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