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