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