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