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