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